home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 5
/
Apprentice-Release5.iso
/
Information
/
CSMP Digest
/
volume 3
/
csmp-digest-v3-006
< prev
next >
Wrap
Text File
|
1995-12-31
|
631KB
|
16,271 lines
Received-Date: Fri, 18 Mar 1994 16:17:18 +0100
From: pottier@clipper.ens.fr (Francois Pottier)
Subject: C.S.M.P. Digest, Issue 3.006
To: csmp-digest@ens.fr
Date: Fri, 18 Mar 94 16:15:51 MET
X-Mailer: ELM [version 2.3 PL11]
Errors-To: listman@ens.fr
Reply-To: pottier@clipper.ens.fr
X-Sequence: 7
C.S.M.P. Digest Fri, 18 Mar 94 Volume 3 : Issue 6
Today's Topics:
68K emulation and PPC toolbox questions.
AE coercion handlers ?
ARGH!!! Whamwhamwham!! (DialogSelect stuff)
An offering: Assembly language code for a high speed copybits
Animation speed: here we go again...
Animation speed: improvement!
Animation speed: more info
Animation: the story continues...
Blank Screen?
C code for scrollable application help
Can C be as fast as Assembler? (next...on the McLaughlin Group)
Color Terminal Emulator
DrawString + Ellipsis character ?
Finder comments on non-Desktop DB volumes?
Finding System Folder (Again)
Free code: Sean's window manager
How does the Finder handle events?
How to determine color of progress bar?
How to draw inits icons?
How to tell a Mac from a Mac?
I know the Mac MM isn't reentrant, but:
If you use SysBeep() for debugging...
Improving DrawText speed (Was: Color Terminal Emulator)
Interface guidelines for extra program files
Intermixing graphics and text
Let's kill 24-bit mode! (was Re: Let's kill System 6!)
Let's kill system 6!
Never beep when using GWorlds. System software bug!
PPC & 68k UPP problems
PPC binaries
Passing data through to completion procs?
Password editing item.. Tricky?
Permanent front windows...
Preference file question!
Reading PICT files != 72 dpi. How ?
Resources on PowerPC
Safer Segments ?
Speeding up animation; questions
System Folder on NONstartup disk
Trap dispatcher overhead
User in a menu?
What happens if my Vertical Retrace task takes too long?
When to StripAddress? (was Re: Let's kill 24-bit mode!)
Why can't I have AEs *in* AEs?
Why use handles at all, though?
Writing To Screen Memory
dirIDs
jGNEFilter Q
password encryption
The Comp.Sys.Mac.Programmer Digest is moderated by Francois Pottier
(pottier@clipper.ens.fr).
The digest is a collection of article threads from the internet newsgroup
comp.sys.mac.programmer. It is designed for people who read c.s.m.p. semi-
regularly and want an archive of the discussions. If you don't know what a
newsgroup is, you probably don't have access to it. Ask your systems
administrator(s) for details. If you don't have access to news, you may
still be able to post messages to the group by using a mail server like
anon.penet.fi (mail help@anon.penet.fi for more information).
Each issue of the digest contains one or more sets of articles (called
threads), with each set corresponding to a 'discussion' of a particular
subject. The articles are not edited; all articles included in this digest
are in their original posted form (as received by our news server at
nef.ens.fr). Article threads are not added to the digest until the last
article added to the thread is at least two weeks old (this is to ensure that
the thread is dead before adding it to the digest). Article threads that
consist of only one message are generally not included in the digest.
The digest is officially distributed by two means, by email and ftp.
If you want to receive the digest by mail, send email to listserv@ens.fr
with no subject and one of the following commands as body:
help Sends you a summary of commands
subscribe csmp-digest Your Name Adds you to the mailing list
signoff csmp-digest Removes you from the list
Once you have subscribed, you will automatically receive each new
issue as it is created.
The official ftp info is //ftp.dartmouth.edu/pub/csmp-digest.
Questions related to the ftp site should be directed to
scott.silver@dartmouth.edu. Currently no previous volumes of the CSMP
digest are available there.
Also, the digests are available to WAIS users as comp.sys.mac.programmer.src.
-------------------------------------------------------
>From herman@ece.cmu.edu (Herman Schmit)
Subject: 68K emulation and PPC toolbox questions.
Date: 16 Mar 1994 19:32:32 GMT
Organization: Electrical and Computer Engineering, Carnegie Mellon
When doing 68K emulation, will a Power Mac do emulation of 68K toolbox
routines, or does the emulator detect those routines and execute the
PowerPC toolbox code for that routine?
I'm also curious exactly why there will not be a 68K->PowerPC machine
code translator in addition to an emulator. I always thought that the
problem with translating between CPUs was not caused by different
instruction sets but by different system/OS calls and different memory
models. If the toolbox will be the same, the system/OS calls are no
longer a problem. Do the Power Macs have a significantly different
memory model?
Even if they have a different memory model, couldn't you do some sort
of emulation of the 68K memory and translate the everything else into
PPC native code? Or is this what is done?
herman
+++++++++++++++++++++++++++
>From rang@winternet.mpls.mn.us (Anton Rang)
Date: 17 Mar 1994 05:13:49 GMT
Organization: Minnesota Angsters
In article <2m7msg$s9f@fs7.ece.cmu.edu> herman@ece.cmu.edu (Herman Schmit) writes:
>When doing 68K emulation, will a Power Mac do emulation of 68K toolbox
>routines, or does the emulator detect those routines and execute the
>PowerPC toolbox code for that routine?
The emulator detects A-traps and dispatches them through the trap
table, as happens on 68K machines. If the trap is written in PowerPC
code, the Mixed Mode Manager switches to PowerPC native mode (if
needed) and then runs it. Similarly, if the trap is in 68K code, the
MMM switches to 68K emulation and then runs it.
>I'm also curious exactly why there will not be a 68K->PowerPC machine
>code translator in addition to an emulator. I always thought that the
>problem with translating between CPUs was not caused by different
>instruction sets but by different system/OS calls and different memory
>models.
First, there is at least one third-party translator available,
FlashPort by Echo Logic. But it requires some input from the
developers to do a good job; you can't just drag-and-drop onto it.
Second, both problems exist. It's not trivial to convert between
different code models *and get reasonable performance*. It can be
done -- VEST on DEC's Alpha VMS machines is truly incredible! -- but
it's very state-of-the-art and probably would have cost Apple many
millions to develop....
--
Anton Rang (rang@winternet.mpls.mn.us)
+++++++++++++++++++++++++++
>From zstern@adobe.com (Zalman Stern)
Date: Fri, 18 Mar 1994 11:55:45 GMT
Organization: Adobe Systems Incorporated
Anton Rang writes
> In article <2m7msg$s9f@fs7.ece.cmu.edu> herman@ece.cmu.edu (Herman Schmit)
writes:
> >When doing 68K emulation, will a Power Mac do emulation of 68K toolbox
> >routines, or does the emulator detect those routines and execute the
> >PowerPC toolbox code for that routine?
>
> The emulator detects A-traps and dispatches them through the trap
> table, as happens on 68K machines. If the trap is written in PowerPC
> code, the Mixed Mode Manager switches to PowerPC native mode (if
> needed) and then runs it. Similarly, if the trap is in 68K code, the
> MMM switches to 68K emulation and then runs it.
In addition, some traps are "fat" and provide both 68K and PowerPC code.
This avoids the overhead of a mixed-mode switch for very small routines.
(Like say SetPort and GetPort.) All of the above applies to any routine
descriptor, not just the ones placed in the trap table. The most common use
is for callbacks passed to toolbox routines, however they can be used within
your own code as well. (There is special support in Mixed Mode to handle the
dispatching and calling conventions of traps of course.)
--
Zalman Stern zalman@adobe.com (415) 962 3824
Adobe Systems, 1585 Charleston Rd., POB 7900, Mountain View, CA 94039-7900
"Do right, and risk consequences." Motto of Sam Houston (via Molly Ivins)
---------------------------
>From paulr@syma.sussex.ac.uk (Paul Russell)
Subject: AE coercion handlers ?
Date: Wed, 2 Mar 1994 16:31:54 GMT
Organization: University of Sussex
Am I right in thinking that there are no default
system AE coercion handlers ? Not even for such
basic conversions as typeChar<->typeExtended ?
Is there a utility for displaying the installed
coercion handlers ?
Are there any available handlers for common
types, either as source or as an extension ?
//Paul
--
| Paul Russell | Internet: P.T.Russell@sussex.ac.uk |
| Experimental Psychology | AppleLink: EP.SUSSEX |
| Sussex University, Falmer | Telephone: +44 273 678639 |
| Brighton BN1 9QG, England | Facsimile: +44 273 678433 |
+++++++++++++++++++++++++++
>From jwbaxter@olympus.net (John W. Baxter)
Date: Wed, 02 Mar 1994 12:43:30 -0800
Organization: Internet for the Olympic Peninsula
In article <1994Mar2.163154.19747@syma.sussex.ac.uk>,
paulr@syma.sussex.ac.uk (Paul Russell) wrote:
> Am I right in thinking that there are no default
> system AE coercion handlers ? Not even for such
> basic conversions as typeChar<->typeExtended ?
There are a bunch of coercions built in to the Apple Event Manager. As it
happens, typeChar<->typeExtended is one of them. They are listed in Inside
Mac: IAC in table 4-1, which occupies ALL of pages 4-43 and 4-44.
There are more "exotic" ones built in, too, such as typeAppleEvent -->
typeAppParameters (by far the easiest way to build THAT monster).
> Is there a utility for displaying the installed
> coercion handlers ?
Yes...there is a little FKey. It puts up a nice list of all the
Application handlers (event, coercion, object extraction, etc) for the
front application, and all the System handlers. It is broken when the
current Finder is in front [if it hurts, don't do it]. It's on the
Developer CDs...since it is there, I don't know where else it may be. It
can also be used to trigger the handlers, although I haven't exercised that
ability.
> Are there any available handlers for common
> types, either as source or as an extension ?
AppleScript installs a whole bunch more. And they are multiplying on the
net. They can get pretty much as outrageous as you may want. I suppose a
hypothetical typeRTF -> hypothetical typePostScript would be possible (but
not written by me).
--
John Baxter Port Ludlow, WA, USA [West shore, Puget Sound]
jwbaxter@pt.olympus.net
+++++++++++++++++++++++++++
>From paulr@syma.sussex.ac.uk (Paul Russell)
Date: Thu, 3 Mar 1994 13:49:08 GMT
Organization: University of Sussex
John W. Baxter (jwbaxter@olympus.net) wrote:
: In article <1994Mar2.163154.19747@syma.sussex.ac.uk>,
: paulr@syma.sussex.ac.uk (Paul Russell) wrote:
: > Am I right in thinking that there are no default
: > system AE coercion handlers ? Not even for such
: > basic conversions as typeChar<->typeExtended ?
: There are a bunch of coercions built in to the Apple Event Manager. As it
: happens, typeChar<->typeExtended is one of them. They are listed in Inside
: Mac: IAC in table 4-1, which occupies ALL of pages 4-43 and 4-44.
: There are more "exotic" ones built in, too, such as typeAppleEvent -->
: typeAppParameters (by far the easiest way to build THAT monster).
Thanks for the above and the rest of your comments - it looks like I
have some sort of problem. I tried writing a small program which just
calls AEGetCoercionHandler for a few different types and I get a -1717
for everything I've tried. I have Apple Event Manager 1.0.1 and
AppleScript 1.0 installed and am running System 7.1. I think both
Apple Event Manager 1.0.1 and AppleScript 1.0 may be out of date
by now so I'll have a dig through the developer CD's and see if
I can find something newer.
//Paul
--
| Paul Russell | Internet: P.T.Russell@sussex.ac.uk |
| Experimental Psychology | AppleLink: EP.SUSSEX |
| Sussex University, Falmer | Telephone: +44 273 678639 |
| Brighton BN1 9QG, England | Facsimile: +44 273 678433 |
+++++++++++++++++++++++++++
>From isis@netcom.com (Mike Cohen)
Date: Thu, 3 Mar 1994 01:48:50 GMT
Organization: ISIS International
paulr@syma.sussex.ac.uk (Paul Russell) writes:
>Am I right in thinking that there are no default
>system AE coercion handlers ? Not even for such
>basic conversions as typeChar<->typeExtended ?
>Is there a utility for displaying the installed
>coercion handlers ?
>Are there any available handlers for common
>types, either as source or as an extension ?
>//Paul
There are default handlers for most numeric types to/from text and from
alias to FSSpec. With AppleScript installed, there are many more coercion
handlers available.
--
Mike Cohen - isis@netcom.com
NewtonMail: MikeC49506 / ALink: D6734 / AOL: MikeC20
+++++++++++++++++++++++++++
>From paulr@syma.sussex.ac.uk (Paul Russell)
Date: Fri, 4 Mar 1994 13:20:57 GMT
Organization: University of Sussex
Mike Cohen (isis@netcom.com) wrote:
: paulr@syma.sussex.ac.uk (Paul Russell) writes:
: >Am I right in thinking that there are no default
: >system AE coercion handlers ? Not even for such
: >basic conversions as typeChar<->typeExtended ?
: >Is there a utility for displaying the installed
: >coercion handlers ?
: >Are there any available handlers for common
: >types, either as source or as an extension ?
: >//Paul
: There are default handlers for most numeric types to/from text and from
: alias to FSSpec. With AppleScript installed, there are many more coercion
: handlers available.
Thanks - I found the FKEY that displays the installed handlers and
although there is a motley assortment of coercion handlers, none
of the expected handlers for text<->float etc seem to be available.
This appears to be the case on several Macs that I have tried this on,
and I have also written a test program which calls AEGetCoercionHandler
which returns -1717 for just about any pair of types I try.
My best guess is that this is something to do with localisation - I am
wondering if the US version of the Apple Event Manager/Apple Script
checks the system version and doesn't install any handlers which might
be country-specific ?
If the above is not the correct explanation then I'd be interested to
hear any other possible explanations for why the usual handlers aren't
available ?
//Paul
--
| Paul Russell | Internet: P.T.Russell@sussex.ac.uk |
| Experimental Psychology | AppleLink: EP.SUSSEX |
| Sussex University, Falmer | Telephone: +44 273 678639 |
| Brighton BN1 9QG, England | Facsimile: +44 273 678433 |
+++++++++++++++++++++++++++
>From lai@apple.com (Ed Lai)
Date: 4 Mar 1994 23:32:40 GMT
Organization: Apple
In article <1994Mar4.132057.18343@syma.sussex.ac.uk>,
paulr@syma.sussex.ac.uk (Paul Russell) wrote:
> Mike Cohen (isis@netcom.com) wrote:
> : paulr@syma.sussex.ac.uk (Paul Russell) writes:
>
> : >Am I right in thinking that there are no default
> : >system AE coercion handlers ? Not even for such
> : >basic conversions as typeChar<->typeExtended ?
>
> : >Is there a utility for displaying the installed
> : >coercion handlers ?
>
> : >Are there any available handlers for common
> : >types, either as source or as an extension ?
>
> : >//Paul
>
> : There are default handlers for most numeric types to/from text and from
> : alias to FSSpec. With AppleScript installed, there are many more coercion
> : handlers available.
>
> Thanks - I found the FKEY that displays the installed handlers and
> although there is a motley assortment of coercion handlers, none
> of the expected handlers for text<->float etc seem to be available.
> This appears to be the case on several Macs that I have tried this on,
> and I have also written a test program which calls AEGetCoercionHandler
> which returns -1717 for just about any pair of types I try.
>
> My best guess is that this is something to do with localisation - I am
> wondering if the US version of the Apple Event Manager/Apple Script
> checks the system version and doesn't install any handlers which might
> be country-specific ?
>
> If the above is not the correct explanation then I'd be interested to
> hear any other possible explanations for why the usual handlers aren't
> available ?
>
> //Paul
>
> --
> | Paul Russell | Internet: P.T.Russell@sussex.ac.uk |
> | Experimental Psychology | AppleLink: EP.SUSSEX |
> | Sussex University, Falmer | Telephone: +44 273 678639 |
> | Brighton BN1 9QG, England | Facsimile: +44 273 678433 |
The FKEY displays the installed handlers, i.e. those handler installed
using AEInstallXXX, but not the built-in handlers. The built-in handlers
are listed in IM. The are built-in typeChar<->numericTypes. However they
are not localized and are not meant for formating of numbers, they are
more like what you expect to see in a debugger.
--
/* Disclaimer: All statments and opinions expressed are my own */
/* Edmund K. Lai */
/* Apple Computer, MS303-3A */
/* 20525 Mariani Ave, */
/* Cupertino, CA 95014 */
/* (408)974-6272 */
zW@h9cOi
+++++++++++++++++++++++++++
>From ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University)
Date: 9 Mar 94 11:59:29 +1300
Organization: University of Waikato, Hamilton, New Zealand
In article <isisCM2FpH.n03@netcom.com>, isis@netcom.com (Mike Cohen) writes:
> paulr@syma.sussex.ac.uk (Paul Russell) writes:
>
>>Am I right in thinking that there are no default
>>system AE coercion handlers ? Not even for such
>>basic conversions as typeChar<->typeExtended ?
>
> There are default handlers for most numeric types to/from text and from
> alias to FSSpec. With AppleScript installed, there are many more coercion
> handlers available.
But one obvious one is missing: converting a pathname string to an alias or
an FSSpec. I _always_ keep forgetting to prefix my pathnames with "file" or
"alias"...
Lawrence D'Oliveiro fone: +64-7-856-2889
Info & Tech Services Division fax: +64-7-838-4066
University of Waikato electric mail: ldo@waikato.ac.nz
Hamilton, New Zealand 37^ 47' 26" S, 175^ 19' 7" E, GMT+13:00
+++++++++++++++++++++++++++
>From lai@apple.com (Ed Lai)
Date: 10 Mar 1994 17:57:10 GMT
Organization: Apple
In article <1994Mar3.134908.28390@syma.sussex.ac.uk>,
paulr@syma.sussex.ac.uk (Paul Russell) wrote:
> John W. Baxter (jwbaxter@olympus.net) wrote:
> : In article <1994Mar2.163154.19747@syma.sussex.ac.uk>,
> : paulr@syma.sussex.ac.uk (Paul Russell) wrote:
>
> : > Am I right in thinking that there are no default
> : > system AE coercion handlers ? Not even for such
> : > basic conversions as typeChar<->typeExtended ?
>
> : There are a bunch of coercions built in to the Apple Event Manager. As it
> : happens, typeChar<->typeExtended is one of them. They are listed in Inside
> : Mac: IAC in table 4-1, which occupies ALL of pages 4-43 and 4-44.
>
> : There are more "exotic" ones built in, too, such as typeAppleEvent -->
> : typeAppParameters (by far the easiest way to build THAT monster).
>
> Thanks for the above and the rest of your comments - it looks like I
> have some sort of problem. I tried writing a small program which just
> calls AEGetCoercionHandler for a few different types and I get a -1717
> for everything I've tried. I have Apple Event Manager 1.0.1 and
> AppleScript 1.0 installed and am running System 7.1. I think both
> Apple Event Manager 1.0.1 and AppleScript 1.0 may be out of date
> by now so I'll have a dig through the developer CD's and see if
> I can find something newer.
>
> //Paul
> --
> | Paul Russell | Internet: P.T.Russell@sussex.ac.uk |
> | Experimental Psychology | AppleLink: EP.SUSSEX |
> | Sussex University, Falmer | Telephone: +44 273 678639 |
> | Brighton BN1 9QG, England | Facsimile: +44 273 678433 |
AEGetCoercionHandler just returns whether an XXXX->YYYY coercion handler
has
been installed, it does not really tell you if a particular coercion
exists.
Built-in handler does not have a fixed address since the PACK can be
relocated
so the address cannot be returned. And if XXXX->YYYY coercion is handled by
the ****->YYYY coercion handler, AEM has no idea that XXXX->YYYY can or
cannot be done through ****->YYYY. So the rule is that it strictly returns
an XXXX->YYYY address if it exists, it is not meant to rule out the
existence of the possibility of XXXX->YYYY coercion.
--
/* Disclaimer: All statments and opinions expressed are my own */
/* Edmund K. Lai */
/* Apple Computer, MS303-3A */
/* 20525 Mariani Ave, */
/* Cupertino, CA 95014 */
/* (408)974-6272 */
zW@h9cOi
+++++++++++++++++++++++++++
>From jonpugh@netcom.com (Jon Pugh)
Date: Sat, 12 Mar 1994 07:19:44 GMT
Organization: NETCOM On-line Communication Services (408 241-9760 guest)
Lawrence D'Oliveiro, Waikato University (ldo@waikato.ac.nz) wrote:
> But one obvious one is missing: converting a pathname string to an alias or
> an FSSpec. I _always_ keep forgetting to prefix my pathnames with "file" or
> "alias"...
This is done and working as part of Jon's Commands 1.1. Interested in beta
testing?
Jon
---------------------------
>From gjw2824@hertz.njit.edu (Greg Weston)
Subject: ARGH!!! Whamwhamwham!! (DialogSelect stuff)
Date: 5 Mar 94 19:58:17 GMT
Organization: New Jersey Institute of Technology, Newark, New Jersey
Howdy, folks. I've been playing with everyone's favorite UI addition:
Floating Windows. I've gotten them to work smoothly and cleanly, and
they interact fine with normal windows and dialogs (modal or not). The
only problem is within a pair of cute little routines called
IsDialogEvent and DialogSelect. They don't like having a (floating)
window in front of the Dialog they're working with.
So, I re-wrote them. (Cough. Embarrased grin.) Still no problem. I'm
left with one teensy little problem:
How in the blazes does DialogSelect do its magic when you have
multiple editTexts in a dialog and either click in a non-current one
or press Tab?!?!
On that topic, IM is silent, and I can't figure out how to
successfully pull off the swap with what they give you. Any thoughts,
suggestions, or even polite chuckles would be appreciated.
Thanks,
Greg
+++++++++++++++++++++++++++
>From cconstan@epdiv1.env.gov.bc.ca (Carl B. Constantine)
Date: Mon, 07 Mar 1994 10:31:52 -0800
Organization: Ministry of Environment, Lands & Parks
In article <1994Mar5.195817.28298@njitgw.njit.edu>, gjw2824@hertz.njit.edu
(Greg Weston) wrote:
> Howdy, folks. I've been playing with everyone's favorite UI addition:
> Floating Windows. I've gotten them to work smoothly and cleanly, and
> they interact fine with normal windows and dialogs (modal or not). The
> only problem is within a pair of cute little routines called
> IsDialogEvent and DialogSelect. They don't like having a (floating)
> window in front of the Dialog they're working with.
>
> So, I re-wrote them. (Cough. Embarrased grin.) Still no problem. I'm
> left with one teensy little problem:
> How in the blazes does DialogSelect do its magic when you have
> multiple editTexts in a dialog and either click in a non-current one
> or press Tab?!?!
>
> On that topic, IM is silent, and I can't figure out how to
> successfully pull off the swap with what they give you. Any thoughts,
> suggestions, or even polite chuckles would be appreciated.
> Thanks,
> Greg
One solution the new IM suggests instead of using dialog Select, you can
use a custom routing to take a look at what kind of window the event
occured in and then process the event that way.
Very usefull if you're dealing with modeless and movableModal Dialogs.
Source: IM Macintosh Toolbox Essentials, ch. 6 Dialog Manager.
--
=========================================================================
Carl B. Constantine B.C. Environment, Lands & Parks
End-User Support Analyst CCONSTAN@epdiv1.env.gov.bc.ca
+++++++++++++++++++++++++++
>From Steve Bryan <sbryan@maroon.tc.umn.edu>
Date: Tue, 8 Mar 1994 15:37:06 GMT
Organization: Sexton Software
In article <1994Mar5.195817.28298@njitgw.njit.edu> Greg Weston,
gjw2824@hertz.njit.edu writes:
>How in the blazes does DialogSelect do its magic when you have
>multiple editTexts in a dialog and either click in a non-current one
>or press Tab?!?!
I can't tell exactly how far along you are in this project but if you
haven't taken a look at the DialogRecord structure you should do so now
(I know, you probably have).
DialogRecord = record
window: WindowRecord;
items: Handle;
textH: TEHandle;
editField: Integer;
editOpen: Integer;
aDefItem: Integer;
end;
You need to manipulate the textH and editField variables. EditField
points to the current text item in the linked list starting at items. Of
course you have to update the current text item before setting up textH
for the new text item. I thought there was some fairly useful information
about this stuff in Inside Mac Volume I. My volume I is at home so I
can't check but try looking there.
+++++++++++++++++++++++++++
>From u9119523@sys.uea.ac.uk (Graham Cox)
Date: Wed, 9 Mar 1994 17:01:47 GMT
Organization: School of Information Systems, UEA, Norwich
In article <cconstan-070394103153@eusacbc.env.gov.bc.ca>,
cconstan@epdiv1.env.gov.bc.ca (Carl B. Constantine) wrote:
> In article <1994Mar5.195817.28298@njitgw.njit.edu>, gjw2824@hertz.njit.edu
> (Greg Weston) wrote:
>
> > Howdy, folks. I've been playing with everyone's favorite UI addition:
> > Floating Windows. I've gotten them to work smoothly and cleanly, and
> > they interact fine with normal windows and dialogs (modal or not). The
> > only problem is within a pair of cute little routines called
> > IsDialogEvent and DialogSelect. They don't like having a (floating)
> > window in front of the Dialog they're working with.
> >
> > So, I re-wrote them. (Cough. Embarrased grin.) Still no problem. I'm
> > left with one teensy little problem:
> > How in the blazes does DialogSelect do its magic when you have
> > multiple editTexts in a dialog and either click in a non-current one
> > or press Tab?!?!
> >
[SNIP!]
If your question is how does it switch from one field to another, then I
can answer!
In the DIALOGRECORD is a field which contains the ID number of the current
editable item. When you hit tab, this is incremented and GetDItem called to
see if the resulting item is an edit field, if not, it increments until it
finds one or until the last item is found, at which point it starts over
from item 1. When it finds an edit field item, it retrieves the text from
the current one and stashes it into the item list as that item's string,
then installs the text from the new one into the teRecord using TESetText,
then selects it with TESetSelect, or if it was a click, calls TEClick. The
DialogRecord also contains the teHandle.
The DialogRecord itself is documented in IM, though this sequence of events
isn't- I had to figure this out for myself once when trying to do something
along the same lines as you.
You can get the dialog record by casting the DialogPtr to type DialogPeek.
Hope this helps!
> =========================================================================
> Carl B. Constantine B.C. Environment, Lands & Parks
> End-User Support Analyst CCONSTAN@epdiv1.env.gov.bc.ca
- ------------------------------------------------------------------------
Love & BSWK, Graham
-Everyone is entitled to their opinion, no matter how wrong they may be...
- ------------------------------------------------------------------------
- ------------------------------------------------------------------------
Love & BSWK, Graham
-Everyone is entitled to their opinion, no matter how wrong they may be...
- ------------------------------------------------------------------------
+++++++++++++++++++++++++++
>From qsi@NU91.wlink.nl (Peter Kocourek)
Date: Tue, 08 Mar 1994 20:55:13 +0100
Organization: (none)
Greg Weston wrote in a message on 05 Mar 94 to All
GW> Howdy, folks. I've been playing with everyone's favorite UI
GW> addition: Floating Windows. I've gotten them to work smoothly
GW> and cleanly, and they interact fine with normal windows and
GW> dialogs (modal or not). The only problem is within a pair of
GW> cute little routines called IsDialogEvent and DialogSelect.
GW> They don't like having a (floating) window in front of the
GW> Dialog they're working with.
GW> So, I re-wrote them. (Cough. Embarrased grin.) Still no problem. I'm
GW> left with one teensy little problem: How in the blazes does
GW> DialogSelect do its magic when you have multiple editTexts in a
GW> dialog and either click in a non-current one or press Tab?!?!
These two issues are separate from one another. Handling Tab presses is far
easier than getting the mouseclick-induced editText change right. In fact, I
haven't been able to get my own routines to do this properly. I was writing my
own replacements for DialogSelect (to handle movable modals and modeless
dialogs, with enhancements) and bumped into this problem. I tried all sorts of
things with the TERecord, but I wasn't able to get the swap done cleanly.
So I cheated. :-) In my generic mouseDown-handling procedure (within my
DialogSelect replacement), I first check to see where the mouseDown occurred.
If it is in an editText field, I check whether it's the currently active
text-input-capable [TIC, my shorthand] item, and in that case a simple TEClick
call will take care of everything. If it is not the active TIC item (you have
to keep track of this separately), and the currently active TIC is not an
editText item, I call the deactivate function for the TIC; this is usually a
custom routine for userItems which contain lists, for instance. One aesthetic
problem with this is, that userItems don't have refCons, so that storing the
ProcPtr's for userItem service routines is a bit cumbersome. Anyway, once your
previously active TIC item is deactivated, you can activate manually the
TERecord, and call TEClick.
If, however, the active TIC item is an editText item, you'll have to "cheat".
Having found no way doing the transition from one editText item to another
cleanly, I simply call the real DialogSelect at that point. Note that I only do
this when I have determined unambiguously, that the action to be taken is
switching from one editText item to anohter.
As for handling Tabs, the situation is a bit easier. You have to find the next
TIC item in your dialog (or the previous one, if the user pressed shift-Tab),
and handle the deactivating and activating as above. The one thing that makes
it doable without "cheating", is that you don't have to place the caret
anywhere within the text of the next editText item (this was causing my
problems), but you either select the entire text, if there is any, or you place
just a caret, if there isn't. I'll include my source code where I do this.
Parts of the code are specific to my implementation. For instance, I store a
struct via a Handle in the window refCon. This struct contains lots of
information about the dialog; you'll have to adapt it to your own needs. You
will have to provide the CanAcceptText and ActivateItem functions for your own
userItems.
(sorry about the formatting)
/*************************************************************************************
* Somehow I'm not sure I should be doing this... requires too much thinking.
* CycleKeyBoardInput is a generic routine that will find and activate the next
(or
* previous) item in the DITL that can accept keyDown events. To do this, it
needs:
* + a DialogPtr, to indicate in which dialog to look, and to get at the
WIHandle.
* + a Boolean isShiftPressed, to determine whether to search forward or
backward in
* the DITL
* + a pointer to a function, that returns a Boolean. If this function,
CanAcceptText,
* returns TRUE, then the userItem (passed as a short to CanAcceptText) can
accept
* keyDown events. This function should be declared along with the other
specific
* functions for this dialog (as in AddressesDialog.c)
* + another pointer to a function, that will either activate or deactivate a
userItem
* in the DITL, that can accept text. {De}Activating editText items is done
here.
*
************************************************************************************/
void CycleKeyboardInput(DialogPtr dPtr, Boolean isShiftPressed,
Boolean (*CanAcceptText)(short), void (*ActivateItem)(WindowInfoHandle,
short, Boolean))
{
WindowInfoHandle aWIHandle; /* my own struct with info */
short numItems, activeItem, queryItem, iType;
aWIHandle = (WindowInfoHandle)GetWRefCon(dPtr);
activeItem = (**aWIHandle).activeItem; /* keeping track of the active TIC */
queryItem = activeItem + (isShiftPressed ? -1 : 1);
numItems = CountDITL(dPtr);
while (queryItem != activeItem) /* check to see if we're back where we
started */
{
if (queryItem == 0) /* handle rollover */
queryItem = numItems;
else if (queryItem == numItems+1)
queryItem = 1;
GetDItem(dPtr, queryItem, &iType, &workHandle, &workRect); /* get item info
*/
if (iType == editText) /* if editText, we're finished */
break;
if (iType == userItem && CanAcceptText(queryItem)) /* same for userItem */
break;
isShiftPressed ? queryItem-- : queryItem++; /* get next item to query */
}
if (queryItem != activeItem) /* found a new one? */
{
short aType;
GetDItem(dPtr, activeItem, &aType, &workHandle, &workRect);
if (aType == userItem)
ActivateItem(aWIHandle, activeItem, FALSE); /* deactivate currently active
user item */
if (iType == editText)
{
SelIText(dPtr, queryItem, 0, 32767); /* select new editText item */
workTEHandle = ((DialogPeek)dPtr)->textH;
}
else if (iType == userItem)
{
if (aType == editText) /* was previously active item an editText? */
TEDeactivate(((DialogPeek)dPtr)->textH);
ActivateItem(aWIHandle, queryItem, TRUE); /* select new userItem */
workTEHandle = NIL;
}
(**aWIHandle).activeItem = queryItem;
UpdateEditMenus(workTEHandle, kSystemTE); /* my own service proc */
}
}
I hope you can make some sense out of all this. :-) Additional notes: CountDITL
is System 7 specific (may come with CTB under System 6), but I don't do System
6 anymore. An example of an ActivateItem function would be for a list to draw a
border around the list, to alert the user that keypresses will go to the list
(to select a cell in the list).
GW> On that topic, IM is silent, and I can't figure out how to
GW> successfully pull off the swap with what they give you. Any
GW> thoughts, suggestions, or even polite chuckles would be appreciated.
<chuckle, polite> :-)
YHS:QSI!
+++++++++++++++++++++++++++
>From gjw2824@hertz.njit.edu (Greg Weston)
Date: 10 Mar 94 20:38:09 GMT
Organization: New Jersey Institute of Technology, Newark, New Jersey
Well, I had three people respond, each with different suggestions, and
got it working with the first one. I'd like to thank Steve Bryan, Carl
Constantine, and Simon Ward for their advice. I had looked through the
IM vol 1 stuff pretty carefully, but the mechanics of the manipulation
really were sketchy. My NIM is 100+ miles away, so I didn't have that
to look through. I have a solution that works quite well, though, and
I'm very happy with the finished product. Thank you kindly, and y'all
will probably see a submission to the standard archives soon.
Greg
---------------------------
>From ejohnson@netcom.com (Eric Johnson)
Subject: An offering: Assembly language code for a high speed copybits
Date: Fri, 18 Mar 1994 07:50:48 GMT
Organization: NETCOM On-line Communication Services (408 241-9760 guest)
About two weeks ago, I had mentioned that I had written some assembly
language code that could beat copybits given certain assumptions. A
number of people (Alex Metcalf and David Wareing) had asked me to send
them some samples. I was going to write up some demo code with it,
but never got around to it due to work obligations.
A few days ago, I sent David an email message with some and a length
explanation. I figured that maybe everyone else could benefit from
the email to. Keep in mind that the following code was my first real
whack at some high speed copybits. I may be breaking a few rules, or
doing bad Mac programmer things. So USE IT AT YOUR OWN RISK.
I believe further enhancements can be made to it, especially given the
wide spread prominence of the 030 and 040. When I first wrote it, the
020 was in much more common use.
This code has evolved into a copybits that will do some very fast
masking. I had used it for a graphics engine that would display
things at a perspective. Where each icon was a perspective block, if
you will. Thus masking was needed. It looks quite sharp. I can go
over that code too, as well as the trick I put in for some fast
masking. As always, you pay for the speed. It needs a bit of memory.
Let me know if this helps anyone. Here is the message I sent to David
Wareing.
<------------->
David,
Okay, here's some code with some explanation off the top of my head.
This code was developed for a tile based adventure game that was never
quite finished. The graphics were a simple display consisting of
11x11 icons where each icon was a 24x24 cicn resource. This type of
display is identical to that of the old Ultima games on the Apple ][
and old PC's. And the more recent Zelda of Nintendo or Civilization
on the Macintosh.
I initially wrote everything in C, and used PlotCIcon to place my color
icons on the screen. In found that to be too slow, because the Mac
was constantly converting the colors in the resource to those
available on the screen. Hence the molases like quality. So I said
to myself, "Screw it, I'm going do it in assembly.".
Even though the code I'm including has been rewritten for a slightly
more complex display, I'm giving this to you so you can follow the
history of its development. It should make more sense this way, and
you'll see some room for improvements along the way. I wrote this as
a beginner Mac programmer, so I may be breaking some rules.
Let's first identify what slows down drawing to the screen. In my
case, I had a few mistakes. The first one was using PlotCIcon. The
Mac was constantly converting the resource into the current colors
available in the port. That's all well and good, in fact that's quite
nice of them. But it slows things down a bit.
To get around this, I created an off screen window that would
warehouse my icons. The benefit is that the off screen window would
have the same color table [CLUT, right?] so any transfer between an
offscreen window and the main screen would be a trivial copy. Thus,
at start time, I painted each icon into the off screen to "coerce" it
into the current system table.
Okay, so I did that. I would then use copy bits to repaint my window.
In my game, I have a two dimensional array with numbers indicating
which icon goes at what location. So, I would get the id number of
the display icon, locate it in my off screen window [the palette of
icons] and use copybits to get it to the window.
Well, that was better, but was still slower than I expected. So, I
got to thinking about how to speed things up. The bottleneck in this
case is copybits. Sure, copybits is fairly fast, but I know a few
things about my icons that it doesn't know. They are all of the same
width, and same height. But how do I put this knowledge to good use?
Let's step back for a second and look at the Motorola architecture.
When I wrote it, I decided to take advantage of the features found in
the 68020's and later. It really starts to do well in the 030. We
won't consider the 68000 because there's not much you can do for that
chip.
The 680x0 has 8 32 bit data registers and 8 32 address registers. You
lose some of the address registers to the system, but all in all,
there's some room to play around in. The 68020 and later have some
code cache and data caches to work with too. In other words, you can
have a loop fill up the instruction cache, and then the CPU can run
faster because all of its code is in the cache.
It's this instruction cacheing that I take full advatange of. In later
developments of this code, I try to take advantage of the data cache.
So, we need to write some assembly language code that will copy 24
bytes at a time from 24 different parts of memory. Remember, in this
case, my icons are 24 bytes wide (24 pixels at 8 bits a pixel). And
the are 24 pixels high. So, we've got 24 blocks of 24 pixels. Each
block starts at a slightly different memory location.
My code loops 24 times, one for each row of 24 bytes. Thus, the code
that copies each row lands in the instruction cache. So, on each
subsequent reitiration of the code, we are running strictly from the
cache. This gives us some good performance. But there's one more
feature too.
Most modern processors have a pipeline where the different parts of
the CPU execute part of an instruction then hand it off to the next
step. It works identically to an assembly line where someone installs
the engine and the next person installs the tires. A new car always
rolls off the line every so often even though it may take a bit for a
car to travel the entire line.
The catch lies with branch instructions. The CPU won't know if the
branch should be taken until its evaluation is complete. But, this
means that the CPU won't necessarily be putting the right instructions
in the pipeline. It would be like producing a car that indicated the
previous cars should be destroyed. This wrecks efficiency.
To get around it, Motorola has provided an instruction, dbra, that
serves as a hint. dbra tells the CPU to branch if the contents of the
data register are not zero. It instructs the CPU to expect the branch
and fill the pipeline with the instructions that would result if a
branch takes place.
So, my loops gets two nice features going. The instruction cache and
it keeps the pipeline going too. Pretty sweet, eh?
My code works in two steps. The first section is the prepatory work
for the loop. I put as much stuff as I can into registers, because
adding and multiplying "in register" is much faster than from memory.
And the instructions are shorter, which means less space is taken up
in the instruction cache.
This point of putting stuff "in register" may seem anal, but remember,
we need to add some values at the end of each iteration of the loop
and keeping stuff as fast and small is good.
Now, let's go over the parameters to the code.
mySource points to the start of the off screen palette.
myDestination points to the start of the off screen drawing space.
xSource and ySource are the x,y coordinates of the pixel that
represents the upper left hand corner of the thing you wish copied.
Keep in mind that these are *PIXEL COORIDINATES* not icon coordinates.
Its up to you to find the start of the icon you wish copied in your
off screen palette of icons. I suppose my code could do it. I just
didn't bother.
xDestination and yDestination are the same xSource and ySource except
for the destination array.
iconSize should be your icon height minues one. In my case, its 23.
int MyCopyBits8(Ptr mySource, Ptr myDestination,
long int xSource, long int ySource,
long int xDestination, long int yDestination,
long int iconSize) {
asm 68000 {
/**
** We need to save the registers that we are going to clobber.
**
** a1 starts out pointing to the top of the pallete, but it .
** will eventually end up pointing to the start of the source
** icon. Same goes for a2.
**
** d2 and d3 are a bit tricky to explain. They are the row
** byte values for the source and destination. A row byte
** value is the number of bytes required to jump down to the
** next row. It needs to be a multiple of four else some
** Mac internals complain. We use these values to find the
** real location of both icons.
**
**/
movem.l a1-a2/d0-d3, -(sp); /* save the regs */
move.l mySource,a1;
move.l myDestination,a2;
move.l #0x0780,d2; /* hard coded row bytes value */
move.l #0x0138,d3; /* hard coded row bytes value */
/**
** The following four lines find the real address of the source
** icon. They do this by following a simple formula.
** real_source = base + y Position * row bytes for Src + x Pos
** This result is placed into a1 as mentioned before.
**/
move.l ySource,d0;
mulu d2,d0;
add.l d0,a1;
add.l xSource,a1;
/** We follow the same formula for the destination address **/
move.l yDestination,d0;
mulu d3,d0;
add.l d0,a2;
add.l xDestination,a2;
/**
** The following will seem a bit weird. Why subtract #20 from the
** row byte values? Keep in mind that as we are copying from the
** source to the destination, we are changing our pointers
** (marching them across the icon). When we are finished copying,
** we need to add the rowBytes-20 to get to the first byte of the
** the next row. Note that 20 is iconSize-3. Yeah, that should be
** that way in the code. Just never bothered to change it.
**/
sub.l #20,d2;
sub.l #20,d3;
move.l iconSize,d0;
/** END OF PREPARTORY WORK **/
/** And now you're ready to start the copy of each row of bytes **/
@1 ;
move.l (a1)+,(a2)+; /** Note that we are increasing our **/
move.l (a1)+,(a2)+; /** pointers as go along here. **/
move.l (a1)+,(a2)+; /** Also note that we copy four **/
move.l (a1)+,(a2)+; /** bytes at a crack. And we do it **/
move.l (a1)+,(a2)+; /** six times. For 24 bytes! **/
move.l (a1),(a2);
add.l d2,a1; /** We need to jump down to the start of **/
add.l d3,a2; /** first pixel in the next row. **/
dbra d0,@1; /** Branch until we are done **/
movem.l (sp)+, a1-a2/d0-d3 /* restore the registers */
}
return(1);
}
--
Eric E Johnson
ejohnson@netcom.netcom.com
---------------------------
>From alex@metcalf.demon.co.uk (Alex Metcalf)
Subject: Animation speed: here we go again...
Date: Sat, 12 Mar 1994 10:14:53 GMT
Organization: Demon Internet
Now that we've exhausted the previous "animation speed" thread,
it's time to start another. :-)
Having got my game code to run (what I considered to be) extremely
fast on my LC475, I thought I'd give it a whirl on our IIsi. Oh no!
Extremely slow animation speed. I know that the IIsi has very slow video,
but what was running at 60fps on an LC475 surely wouldn't be reduced to
less than 10fps on a IIsi.
One of the things I thought might be causing the problem was that I
still might be having problems matching colour tables between the GWorld
and the window on-screen. I'm creating a normal colour window, and making
it the size of the screen (0,0,640,480). I'm not changing its palette in
any way. Then I'm using NewGWorld with a pixel depth of 0, which is meant
to optimise CopyBits calls with the screen. It's also meant to use the
colour table info and screen depth of the deepest monitor intercepting the
given rectangle. Since I've only got one monitor, this shouldn't be the
problem.
However, response still seems to be unreasonbly sluggish on the
IIsi: whether its in gray scale or colour, the speed is disappointing.
I believe Andrew Welch (hope I spelt your name right) reads this
area regularly: for Maelstrom, what is the animation speed like on low end
'030 Macs? I know you use heavily optimised assembler for your animation,
but I don't think that what I'm doing (CopyBits) should case such a
dramatic difference in animation speed. Is there any way to make CopyBits
completely ignore the colour table differences?
Interesting ideas and suggestions are always appreciated.
Alex
--
Alex Metcalf, Mac programmer in C, C++, HyperTalk, assembler
Internet, AOL, BIX: alex@metcalf.demon.co.uk
AppleLink: alex@metcalf.demon.co.uk@internet#
CompuServe: INTERNET:alex@metcalf.demon.co.uk
Delphi: alex@metcalf.demon.co.uk@inet#
FirstClass: alex@metcalf.demon.co.uk,Internet
Fax (UK): (0570) 45636
Fax (US / Canada): 011 44 570 45636
+++++++++++++++++++++++++++
>From Arsenault_C@msm.cdx.mot.com (Chris Arsenault)
Date: Tue, 15 Mar 1994 12:29:41 -0500
Organization: Motorola Codex
In article <alex-120394101542@metcalf.demon.co.uk>,
alex@metcalf.demon.co.uk (Alex Metcalf) wrote:
> However, response still seems to be unreasonbly sluggish on the
> IIsi: whether its in gray scale or colour, the speed is disappointing.
It sounds like you're okay with your color tables and CopyBits.
You might be running into a hardware problem. There is no separate VRAM
for video on the IIsi (or IIci). The IIsi has 1 MB on the motherboard, a
portion of which it uses as video RAM. Not that I've investigated this,
but I remember reading that if the disk cache is boosted to occupy the
majority of motherboard RAM, then the video driver uses the SIMMs instead
and because the SIMM RAM doesn't have to deal with a bank switch wait you
can get approx. a 30% speed increase.
The unfortunate part about this is that it's not really software
controllable - it's sort of up to the user.
Chris
--
#include <UsualLegalDisclaimers.h>
---------------------------
>From alex@metcalf.demon.co.uk (Alex Metcalf)
Subject: Animation speed: improvement!
Date: Sun, 6 Mar 1994 23:16:59 GMT
Organization: Demon Internet
I discovered something quite interesting this afternoon, which has
almost doubled the speed of the sprite animation in my game.
Just a quick recap: my game copies the background (behind the
sprites) to a gworld, copies the sprites the same gworld, and then copies
that rectangle to the screen. In all, I was using 5 CopyBits for the
background, 5 CopyMasks for the sprites, and 5 CopyBits for copying to the
screen.
Someone originally suggested that I combined all the rectangles
into a region and do a single CopyBits call. However, it turned out to be
slower! Go figure. I guess the individual CopyBits calls outstrip the
RectRgn and UnionRgn calls.
This afternoon, I thought I'd give it another shot, in case I'd
missed something (or done a goofy error which was slowing things down).
This time, for no particular reason, I chose to combine the rectangles for
my CopyBits calls to the screen, and only do the single CopyBits call.
I gave it a go and... WHOAH! Unbelievable speed increase (almost
200%, 60 fps). It seems that CopyBits calls have much more overhead when
copying to the screen rather than copying between offscreen gworlds. I
guess this is because it checks screen depth, colour tables, etc. etc.
To give you an idea of the speed increase: with the extra "time" I
had in my game loop, I was able to add another 4 sprites to the screen,
resulting in another 4 CopyBits calls and 4 CopyMask calls. Even then, it
was still faster than when I was using individual CopyBits calls to the
screen!
So, I've found that the fastest way (with normal QuickDraw
routines) to make my animation work is to use individual CopyBits calls for
sprites between GWorlds, and then a single CopyBits call when it's all
ready to come to the screen.
Here's my code snippet for the copy-to-screen, where gWorldRect is
0,0,640,480 (full screen). I guess I don't need the second SetEmptyRgn
call.
(I use "t" to denote local variables).
// ------
SetEmptyRgn (tCopyRgn);
SetEmptyRgn (tRectRgn);
tObject = gFirstObject;
while (tObject != nil)
{
if (!tObject->fVisible)
{
tObject = (GameObject) tObject->fNextObject;
continue;
}
RectRgn (tRectRgn, &tObject->fAnimEnclosureRect);
UnionRgn (tRectRgn, tCopyRgn, tCopyRgn);
tObject = (GameObject) tObject->fNextObject;
}
CopyBits ((BitMap *) *tPixMap[3], (BitMap *)
&gGameWindow->portPixMap,
&gWorldRect, &gWorldRect, srcCopy, tCopyRgn);
// ------
On a slightly different topic: thanks to some code by Francis
(Francis H Schiffer 3rd), I was able to test my game loop to see where the
time was being used up. I knew that the copying of graphics takes up quite
a lot of time, but I'd never imagined that it tool 98% of the time!
Needless to say, that is what inspired me to have another go at improving
the CopyBits speed...
Thanks again to all those who have given suggestions and code
snippets.... they've all been very useful (or at least, interesting!).
Alex
--
Alex Metcalf, Mac programmer in C, C++, HyperTalk, assembler
Internet, AOL, BIX: alex@metcalf.demon.co.uk
AppleLink: alex@metcalf.demon.co.uk@internet#
CompuServe: INTERNET:alex@metcalf.demon.co.uk
Delphi: alex@metcalf.demon.co.uk@inet#
FirstClass: alex@metcalf.demon.co.uk,Internet
Fax (UK): (0570) 45636
Fax (US / Canada): 011 44 570 45636
+++++++++++++++++++++++++++
>From u9119523@sys.uea.ac.uk (Graham Cox)
Date: Mon, 7 Mar 1994 11:23:35 GMT
Organization: School of Information Systems, UEA, Norwich
In article <alex-060394231740@metcalf.demon.co.uk>,
alex@metcalf.demon.co.uk (Alex Metcalf) wrote:
>
> I discovered something quite interesting this afternoon, which has
> almost doubled the speed of the sprite animation in my game.
>
[SNIP!]
I also read somewhere that CopyBits with a mask region parameter is faster
than CopyMask- you might want to try this and see if it's true.
- ------------------------------------------------------------------------
Love & BSWK, Graham
-Everyone is entitled to their opinion, no matter how wrong they may be...
- ------------------------------------------------------------------------
+++++++++++++++++++++++++++
>From Tony Myles <tony.myles@3do.com>
Date: 7 Mar 1994 21:45:34 GMT
Organization: The 3DO Company
In article <alex-060394231740@metcalf.demon.co.uk> Alex Metcalf,
alex@metcalf.demon.co.uk writes:
[stuff deleted]
> So, I've found that the fastest way (with normal QuickDraw
>routines) to make my animation work is to use individual CopyBits calls
for
>sprites between GWorlds, and then a single CopyBits call when it's all
>ready to come to the screen.
[stuff deleted]
Hey, thats cool. Hmm, just out of curiosity, what kind of Mac are you
running this on? I think I tried this a long time ago on a Q800, and it
was still slower than individual CopyBits calls to the screen. I'll have
to try it again though, I can't remember if I did it quite the way you
describe.
...Tony
- ---------------------------------------------
Tony Myles work: tony.myles@3do.com
The 3DO Company home: suiryu@aol.com
+++++++++++++++++++++++++++
>From alex@metcalf.demon.co.uk (Alex Metcalf)
Date: Tue, 8 Mar 1994 13:38:19 GMT
Organization: Demon Internet
In article <2lg79u$lp8@mac_serv.3do.COM>, Tony Myles <tony.myles@3do.com>
wrote:
> In article <alex-060394231740@metcalf.demon.co.uk> Alex Metcalf,
> alex@metcalf.demon.co.uk writes:
> [stuff deleted]
> > So, I've found that the fastest way (with normal QuickDraw
> >routines) to make my animation work is to use individual CopyBits calls
> for
> >sprites between GWorlds, and then a single CopyBits call when it's all
> >ready to come to the screen.
> [stuff deleted]
>
>
> Hey, thats cool. Hmm, just out of curiosity, what kind of Mac are you
> running this on?
> <snip>
I'm running this on an LC475. I believe I've got all the colour tables
matched up correctly, and the source and destination rectangles are the
same (and the bit depths).
Alex
--
Alex Metcalf, Mac programmer in C, C++, HyperTalk, assembler
Internet, AOL, BIX: alex@metcalf.demon.co.uk
AppleLink: alex@metcalf.demon.co.uk@internet#
CompuServe: INTERNET:alex@metcalf.demon.co.uk
Delphi: alex@metcalf.demon.co.uk@inet#
FirstClass: alex@metcalf.demon.co.uk,Internet
Fax (UK): (0570) 45636
Fax (US / Canada): 011 44 570 45636
---------------------------
>From alex@metcalf.demon.co.uk (Alex Metcalf)
Subject: Animation speed: more info
Date: Thu, 3 Mar 1994 00:25:29 GMT
Organization: Demon Internet
Thanks to those who sent replies to me about improving the
animation speed in my game.
I thought I'd be a little more specific in this description about
exactly what I'm doing, and (as always) I appreciate any feedback.
I have an arcade game which I would like to run at 30 fps on a
68030 Mac or better. It currently DOES run at 30 fps on my LC475, but only
just, and since that's on a 68LC040, I don't stand much chance of 30 fps on
an 030!
In my game, there are 5 or 6 sprites always on the screen, each of
them 24 x 24 pixels in size. There are a number of calculations that I do
with them each time through my 2 tick "loop", but I'm assuming that I can
get the most speed increase by improving my animation code.
I have four (yeah, four) offscreen gworlds, three of them in 8 bit
and 1 in 1 bit. I'll call the 1 bit one the "mask world", and the other
ones worlds "one", "two", and "three".
In world one, I have all my sprite animations, placed there from a
PICT resource. In the mask world, I have the masks for the sprites, all
with exactly the same rectangles as the ones in world one.
In world two, I have the background. I'm using world 3 as the
destination world for preparing to copy to the screen window.
Every time through my loop, I first copy all the background rects
to world three, each one covering the previous location and the next
location of a sprite. This is done with a CopyBits call between worlds.
Then, I use CopyMask to copy the sprites (from world one and the mask
world) on to the background (world three). Finally, I copy each of the
background rects onto the screen, again using CopyBits.
So in summary: I make 6 CopyBits calls between worlds, 6 CopyMask
calls between worlds, and 6 CopyBits calls from the world to the screen.
The rectangles being copied are no more than 32 x 32.
How can I speed this up? I know that assembly programming would be
useful here, but hacking up an assembler copy between gworlds is a new
project to me. I would like to get the animation up to a speed where I can
do 30 fps on a 20mhz 68030, with slow screen redraw (a.k.a. our Mac IIsi).
Thanks in advance for any help you can give me.
Alex
--
Alex Metcalf, Mac programmer in C, C++, HyperTalk, assembler
Internet, AOL, BIX: alex@metcalf.demon.co.uk
AppleLink: alex@metcalf.demon.co.uk@internet#
CompuServe: INTERNET:alex@metcalf.demon.co.uk
Delphi: alex@metcalf.demon.co.uk@inet#
FirstClass: alex@metcalf.demon.co.uk,Internet
Fax (UK): (0570) 45636
Fax (US / Canada): 011 44 570 45636
---------------------------
>From alex@metcalf.demon.co.uk (Alex Metcalf)
Subject: Animation: the story continues...
Date: Sun, 6 Mar 1994 00:45:45 GMT
Organization: Demon Internet
Just a quick update on my original question about speeding up
animation in my game code.
Thanks to all those who gave suggestions for speeding things up:
I'm sorry I haven't had a chance to reply to each of you individually, but
I've had a huge amount of email (about 50 messages a day) and I'm finding
it hard to keep up. Along side this game, I'm working on about 5 or 6
different HyperCard external projects, and that mail (together with regular
newsletters and listserv discussions) makes life quite busy!
Anyway, here are a few of the suggestions I've tried:
o A suggestion was made that rather than CopyBits each of the sprites from
one world to another, I should combine them into a single region and make
only one CopyBits call.
Here's the way I was doing it before:
...
tObject = gFirstObject;
while (tObject != nil)
{
if (!tObject->fVisible)
{
tObject = (AppObject) tObject->fNextObject;
continue;
}
CopyBits ((BitMap *) *tPixMap[2], (BitMap *) *tPixMap[3],
&tObject->fAnimEnclosureRect,
&tObject->fAnimEnclosureRect, srcCopy, nil);
tObject = (AppObject) tObject->fNextObject;
}
...
And here's the way I tried doing it, using only a single CopyBits call.
gWorldRect is the enclosing rectangle for the gworld.
...
SetEmptyRgn (gCopyRgn);
tObject = gFirstObject;
while (tObject != nil)
{
if (!tObject->fVisible)
{
tObject = (AppObject) tObject->fNextObject;
continue;
}
RectRgn (gRectRgn, &tObject->fAnimEnclosureRect);
UnionRgn (gCopyRgn, gRectRgn, gCopyRgn);
tObject = (AppObject) tObject->fNextObject;
}
CopyBits ((BitMap *) *tPixMap[2], (BitMap *) *tPixMap[3],
&gWorldRect, &gWorldRect, srcCopy, gCopyRgn);
...
The second section of code being slower than the first!
o Someone else had suggested that rather than do a CopyMask call, I could
do a CopyBits call with a region (apparently being 60% faster). However,
while the mask for CopyMask masks out the source, the region for CopyBits
masks out the destination. Therefore, unless I can change the position of a
region each time I copy a sprite to the screen, I'm not sure the region
param in CopyBits will help.
Thanks again for all those who have helped out: further suggestions
are always welcomed. I've learned a whole lot more about CopyBits and
CopyMask now!
Thanks,
Alex
--
Alex Metcalf, Mac programmer in C, C++, HyperTalk, assembler
Internet, AOL, BIX: alex@metcalf.demon.co.uk
AppleLink: alex@metcalf.demon.co.uk@internet#
CompuServe: INTERNET:alex@metcalf.demon.co.uk
Delphi: alex@metcalf.demon.co.uk@inet#
FirstClass: alex@metcalf.demon.co.uk,Internet
Fax (UK): (0570) 45636
Fax (US / Canada): 011 44 570 45636
---------------------------
>From mprince@mail.trincoll.edu (Matthew Prince)
Subject: Blank Screen?
Date: Wed, 2 Mar 1994 16:52:07 GMT
Organization: Trinity College
I'm curious what exactly I need to do to blank the entire screen. When
I try to create a window that is the entire size of the GrayRgn I am
able to cover up everything but the menu bar. Is there then a
hideMenuBar command or something? Also, when I PaintRect the area
defined by the GrayRgn to black a strip about the width of and right
below the menu bar is left white. Any help would be appreciated.
Matthew Prince
mprince@mail.trincoll.edu
+++++++++++++++++++++++++++
>From kenlong@netcom.com (Ken Long)
Date: Thu, 3 Mar 1994 03:53:58 GMT
Organization: NETCOM On-line Communication Services (408 241-9760 guest)
Yes. You hide your menuBar before you show your window. That way the
window is not 20 pixels down with the user's desktop textuer peeking over
the top.
The "HideMenuBar" and "ShowMenuBar routines in NewShuttle 1.0d3 are about
as common as they come. I consulted 3 or 4 other working menu bar
hide/show sources before finally deciding on that one.
That Shuttle source is kind of a cheapo. It uses a "full screet window"
as long as you use a 512 x 384 monitor. Unless your window is based on
screenBits.bounds, as apple points out, such specific sized main windows
are user unfriendly. But you also have to get fancy about positioning
and/or sizing your window contents if you are going to make users with
monitors over 14" happy, too. But scaling your screen objects is not
very viable - it usually makes them look odd.
You could do a monitor check and if it's larger than 14", don't hide the
MBar and center the window. Another trick, as in "Out of This World" is
to have all black outside the window. you could hide MBar, fill the rgn
with black, and center your window within it. That looks okay regardless
of window size (wintin reason). It that particular game, a click outside
the action window updates the desktop, washing away the black. A click
back in the action window, blacks it out, again. Nicely done.
There are probably more 14" monitors than any other. The 12"s were
popular when they first came out, but I wish I didn't get one.
Some people, if the program is thoroughly done, will make sets of sizes
of program parts for different monitors. The program would have to be
worth it, and it would be done to increase the purchaser base potential.
Here's some hide/show MBar, in C:
RgnHandle mBarRgn; // First we need to "get a holt of" the MBar.
short *mBarHeightPtr;
short oldMBarHeight;
void HideMenuBar (void)
{
Rect mBarRect;
GrayRgn = GetGrayRgn ();
mBarHeightPtr = (short *) 0x0BAA;
oldMBarHeight = *mBarHeightPtr;
*mBarHeightPtr = 0;
mBarRect = screenBits.bounds;
mBarRect.bottom = mBarRect.top + oldMBarHeight;
mBarRgn = NewRgn ();
RectRgn (mBarRgn, &mBarRect);
UnionRgn (GrayRgn, mBarRgn, GrayRgn);
PaintOne (0L, mBarRgn);
}
void ShowMenuBar (void)
{
*mBarHeightPtr = oldMBarHeight;
DiffRgn (GrayRgn, mBarRgn, GrayRgn);
DisposeRgn (mBarRgn);
}
And here's how they are called:
main (void)
{
Do_Init_Managers (); // Gee! What's this do?
Set_Data_Array (); // Some initializations.
Init_Variables (); // More init.
HideMenuBar (); // Take a little off the top.
Set_Up_Window (); // Get ready for showtime.
HideCursor (); // Get rid of "the fly."
Main_Event_Loop (); // ACTION!
ShowCursor (); // Action's over, bring back some control.
ShowMenuBar (); // Bring this back.
DisposeWindow (&window);// Dump this, an the RAM in rode in on.
ExitToShell (); // Get back home, Loretta!
} // We're in the Finder.
-Ken-
---------------------------
>From rod@faceng.anu.edu.au
Subject: C code for scrollable application help
Date: 3 Mar 1994 22:19:21 GMT
Organization: Department of Engineering, ANU, Australia
I recall from somewhere that there exists some code example
for providing a scrollable text window designed for providing
help information (possibly with an indexing facility). Can someone
direct me to the source (if it exists)?
My Freeware application has full Balloon help but I'd like to complement
it with information akin to readme files.
Thanks in advance.
Rod
+++++++++++++++++++++++++++
>From kidwell@wam.umd.edu (Christopher Bruce Kidwell)
Date: 4 Mar 1994 14:30:05 GMT
Organization: University of Maryland, College Park
In article <2l5npaINN75o@dubhe.anu.edu.au>, <rod@faceng.anu.edu.au> wrote:
>I recall from somewhere that there exists some code example
>for providing a scrollable text window designed for providing
>help information (possibly with an indexing facility). Can someone
>direct me to the source (if it exists)?
on mac.archive.umich.edu: /development/source/help.cpt.hqx
It uses a styled TEXT resource to display scrollable text with a popup
menu to jump to different sections. That version shows the help in a
modal dialog box -- I don't know if there's a moveable modal version
out there anywhere.
Chris Kidwell
kidwell@wam.umd.edu
+++++++++++++++++++++++++++
>From chuck@gte.com (Chuck Hoffman)
Date: Fri, 4 Mar 1994 15:19:53 GMT
Organization: GTE Laboratories
In article <2l5npaINN75o@dubhe.anu.edu.au>, rod@faceng.anu.edu.au wrote:
> I recall from somewhere that there exists some code example
> for providing a scrollable text window designed for providing
> help information (possibly with an indexing facility). Can someone
> direct me to the source (if it exists)?
>
> My Freeware application has full Balloon help but I'd like to complement
> it with information akin to readme files.
>
> Thanks in advance.
>
> Rod
You might find the Help routines useful in the sample application Chassis
6.0. The text is simple, non-styled text.
The text and the selection list are both scrollable.
The window is not a dialog, and can remain open while other windows are in
use.
The text is kept in the resource fork.
The Help menu item is on the Apple menu. In release 6.1 it will be moved
to the Help (baloon) menu. (6.1 will also be AppleEvent aware.)
Chassis 6.0 is freeware. It is available at mac.archive.umich.edu and its
mirror sites, also at CompuServe and America OnLine. Chassis 6.0 is also
available directly from us at ftp.gte.com, file
/pub/chuck/Chassis_6.0.sea.hqx
DO NOT USE THE VERSION AT SUMEX-AIM.STANFORD.EDU. Inexplicably, they never
posted the new version. The one they have, 4.3 or so, is not 32-bit clean
and won't compile with THINK C 6.0. (Don't ask me... I sent the new
version to them twice.)
--
Chuck Hoffman
GTE Laboratories, Waltham, MA, USA
617-466-2131
- ------------------------------------------------
I'm not sure why we're here, but I am sure that
while we're here we're supposed to help each other.
- ------------------------------------------------
+++++++++++++++++++++++++++
>From Robert Hess <robert_hess@macweek.ziff.com>
Date: Wed, 9 Mar 1994 02:40:56 GMT
Organization: MacWEEK
In article <2l7gld$kgq@cville-srv.wam.umd.edu> Christopher Bruce Kidwell,
kidwell@wam.umd.edu writes:
>on mac.archive.umich.edu: /development/source/help.cpt.hqx
>It uses a styled TEXT resource to display scrollable text with a popup
>menu to jump to different sections. That version shows the help in a
>modal dialog box -- I don't know if there's a moveable modal version
>out there anywhere.
You!re thinking of James Walker!s !show_help!, version 2.0 of which
offers a
movable modal.
=======================================================================
====
Robert Hess, WEEKgeek AppleLink: WNDZSX
MacWEEK CompuServe: 72511,333
301 Howard America Online: MacWEEK
San Francisco, Calif. 94105 MCI: RHESS
(415) 243-3576 days Internet:
(415) 243-3651 fax
robert_hess@macweek.ziff.com
(415) 647-5549 nights
I speak for myself. And sometimes not even that.
=======================================================================
====
---------------------------
>From mfi@i-link.com (MicroFrontier Inc.)
Subject: Can C be as fast as Assembler? (next...on the McLaughlin Group)
Date: 28 Feb 1994 09:37:13 -0600
Organization: I-Link, Ltd., Des Moines, IA, USA - 515/255-2754
OK, I've heard both sides of the story here...some developers say that C
can be as fast as assembler (or at least very, very close), provided it is
written well enough. Other say that C code doesn't get anywhere near the
speed of assembler, no matter how it's written.
Now, I would imagine that C can get closer to assembly depending on the
task that is being done....what tasks would those be?
What's the best way to optimize C?
And....which compiler (MPW C, Symantec C, or Metrowerks C) do you think
produces the fastest C code (with all optimization turned on)? Which do
you think produces the best quality code (if being the fastest doesn't
make it the best quality by default)?
Please post responses to the net...I'm sure this is something we can all
benefit from. Also, please try to keep it civil. :-)
-kevin
+++++++++++++++++++++++++++
>From chyang@quip.eecs.umich.edu (Chung-Hsiung Yang)
Date: 28 Feb 1994 16:11:50 GMT
Organization: University of Michigan EECS Dept., Ann Arbor, MI
In article <2kt339$589@ilink1.i-link.com>, mfi@i-link.com (MicroFrontier Inc.) writes:
|>
|>
|> OK, I've heard both sides of the story here...some developers say that C
|> can be as fast as assembler (or at least very, very close), provided it is
|> written well enough. Other say that C code doesn't get anywhere near the
|> speed of assembler, no matter how it's written.
|>
|> Now, I would imagine that C can get closer to assembly depending on the
|> task that is being done....what tasks would those be?
|>
|> What's the best way to optimize C?
I don't think this is really a good way to look at both sides of
the world. I tend to agree that assembler will be faster than C generated
code because programming in assembler requires the programmer to optimize
(some what) the code as you go alone because you are dealing
with much lower semantics than C. On the other hand, the level of optimization
one could do with C is really more dependent on the compiler itself.
But look what you are doing here. What do you want to do with
assembler vs. C? If you restrict yourself to the assembler world, then
you are limited to pretty small programs with pretty limited software
architecture. Maybe you could write routines
for a small, but very fast computation that does for example some process
in digital signal processing. Because of the overhead in C, you would
probably not be able to achieve the speed that you could obtain with C.
But imagine yourself writing a 100,000 line code in C. Quite a
big project. Imagin writing the same code in assembly, you will probably
have to write close to a million line or more. When you get to a million
lines of code in assember, how do you optimize it? It is a scary thought,
I wouldn't do it. In this case I would rather depend on a well designed
C compiler to do the job. In this case, I think for very big programs C
would very likely produce faster codes because there is no way for human
beings to program codes that big in assembly. Also when you get to
that programs that size, there are many tricks that one could play to
optimize the code than assembly because, the notion of a high level
software architecture such as object oriented design just could not be
easily achieved by assembly. (You could do it, but it will be very hard).
- Chung Yang
|> And....which compiler (MPW C, Symantec C, or Metrowerks C) do you think
|> produces the fastest C code (with all optimization turned on)? Which do
|> you think produces the best quality code (if being the fastest doesn't
|> make it the best quality by default)?
|>
|> Please post responses to the net...I'm sure this is something we can all
|> benefit from. Also, please try to keep it civil. :-)
|>
|>
|>
|> -kevin
+++++++++++++++++++++++++++
>From mssmith@afterlife.ncsc.mil (M. Scott Smith)
Date: Mon, 28 Feb 1994 16:30:42 GMT
Organization: The Great Beyond
In article <2kt546$23o@zip.eecs.umich.edu> chyang@quip.eecs.umich.edu (Chung-Hsiung Yang) writes:
>In article <2kt339$589@ilink1.i-link.com>, mfi@i-link.com (MicroFrontier Inc.) writes:
>|>
>|>
>|> OK, I've heard both sides of the story here...some developers say that C
>|> can be as fast as assembler (or at least very, very close), provided it is
>|> written well enough. Other say that C code doesn't get anywhere near the
>|> speed of assembler, no matter how it's written.
>|>
>|> Now, I would imagine that C can get closer to assembly depending on the
>|> task that is being done....what tasks would those be?
>|>
>|> What's the best way to optimize C?
Well, first, I'd say in many cases a lot of blame is put on the compiler
producing "unoptimized" code when the user could in fact be optimizing
their program.
Meaning, often great speed increases can be seen by changing the way
your program does certain things. If you do a sort, are you using a
bubble sort or a quicker sort? Things like that. Once you've done a
good job in that arena, then it comes time when you can benefit from
better code production.
Most compilers (such as Think C) have a "dissassemble" option that
allow you to look at the assembly the compiler is producing. This is
helpful if you know assembly; if you don't, it may not be too useful.
But if you can read assembly, you can see exactly how the compiler is
interpreting your code and try making modifications to your code so
that the resultant assembly is better. Compilers are smart, but they're
not geniouses -- often switching two lines around will signal the compiler
to use some trick to make something much quicker.
I wouldn't recommend writing in Assembly unless you absolutely need
to; that will be weighted yourself down with concrete bricks when you
want to take your program into the future. The PowerPC is an excellent
case in point. The programmers who are porting their applications in
two days are the ones who don't have any of their code in assembly.
But a knowledge of 680x0 or PPC assembly is useful; again, you can
tweak your C code around so it results in better assembly production
with your compiler, without jeopardizing future compatibility.
>|> And....which compiler (MPW C, Symantec C, or Metrowerks C) do you think
>|> produces the fastest C code (with all optimization turned on)? Which do
>|> you think produces the best quality code (if being the fastest doesn't
>|> make it the best quality by default)?
I think this is impossible to say. Each compiler is different, and
each one might produce better code in some places and not others.
Unless one has obvious code generator flaws, they're all probably
pretty good. Code optimization (on the compiler's part) is tricky stuff,
from what I understand. Remember: the compiler basically just does the
"brute force" work of taking your C and transforming it into working,
equivalent assembly. This doesn't require much "smarts" on the compiler's
part.
To look at the C code, and to find tricks for performing the same
function with less instructions, takes great problem-solving skills and
insight which humans often have, but which is difficult to duplicate
in computers.
Each compiler author will no doubt provide that "intelligence" in
their optimizers in different ways. Each compiler probably knows
different tricks. One routine of yours might result in lots of
tricks with compiler X, but none in compiler Y. But with your next
routine the reverse might be true.
I don't know how to define "best quality" in terms other than speed.
Presumably, a compiler is going to produce _100% working code_. There's
no room for errors (on the compiler's part, anyway). So you'd expect
any code a compiler produces to work. The next criterion is "how quickly
does it work?" This is where the optimization comes in. I can't
really think of better ways to measure quality of code generation,
if you make the assumption that any code coming from a compiler isn't
going to have any bugs introduced by the compiler. (That may not always
be a valid assumption.)
Just my thoughts..
Scott
- -
M. Scott Smith (mssmith@afterlife.ncsc.mil)
Macintosh developer.. Student.. Ski bum. Eater of Kellog's Frosted Flakes.
"Last stop for fuel on the information highway"
+++++++++++++++++++++++++++
>From neeri@iis.ee.ethz.ch (Matthias Neeracher)
Date: 28 Feb 94 18:05:12
Organization: Integrated Systems Laboratory, ETH, Zurich
In article <2kt339$589@ilink1.i-link.com>, mfi@i-link.com (MicroFrontier Inc.) writes:
> OK, I've heard both sides of the story here...
Really? I haven't seen a hardcore assembler advocate here in a long time.
> some developers say that C
> can be as fast as assembler (or at least very, very close), provided it is
> written well enough. Other say that C code doesn't get anywhere near the
> speed of assembler, no matter how it's written.
Assembler is much slower than C in several respects:
- Almost all code (with a few exceptions) takes longer to write, debug, and
maintain in Assembler. Note that for the same reasons, C++ is also faster
than C, Eiffel is faster than C++, and Perl for some tasks is much faster
than all of them.
- You will find it easier to identify and rewrite speed critical parts in a C
program than in an assembler program.
- A C application compiled with an "Optimizing for PowerPC" compiler will
run circles around your 680X0 assembler code.
> Now, I would imagine that C can get closer to assembly depending on the
> task that is being done....what tasks would those be?
Depends also a lot on the compiler and the target processor. The 680X0 is
a reasonable code generation target, and so is the PowerPC. In some ways, the
PowerPC will be easier, but new factors like instruction scheduling come into
play. I think assembly language progarmmers will have a harder time beating
compilers on PowerPCs, since instruction scheduling is rather hard to do in
one's head (Except if you are the infamous Mel, who programmed rotating disk
memory machines).
> What's the best way to optimize C?
Use a good compiler. Profile. Rewrite critical sections. repeat.
> And....which compiler (MPW C, Symantec C, or Metrowerks C) do you think
> produces the fastest C code (with all optimization turned on)?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
One problem I ahve with Mac C compilers is that at least for some of them,
turning on optimizaion is too dangerous to do for an entire program.
> Which do
> you think produces the best quality code (if being the fastest doesn't
> make it the best quality by default)?
I'd take a reliable compiler over a fast compiler or one producing fast code
anytime.
> Also, please try to keep it civil. :-)
With a topic like this??
Matthias
- ---
Matthias Neeracher neeri@iis.ethz.ch
"And I won this ribbon in a Degradation Contest at the Teheran
meeting of Junkies Anonymous" -- William Burroughs, _The Naked Lunch_
+++++++++++++++++++++++++++
>From peter@ncrpda.curtin.edu.au (Peter N Lewis)
Date: 1 Mar 1994 12:03:20 +0800
Organization: NCRPDA, Curtin University
mfi@i-link.com (MicroFrontier Inc.) writes:
>OK, I've heard both sides of the story here...some developers say that C
>can be as fast as assembler (or at least very, very close), provided it is
>written well enough. Other say that C code doesn't get anywhere near the
>speed of assembler, no matter how it's written.
C or Pascal produce about teh same quality code. It's generally about
half the speed of reasonably tight assembly code (although an important
thing to remember before converting your code from C/Pascal to asm is
that while you might get a double speed imporvement, redesigning the
*algorithm* used may get you orders of magnitude of imporvement, and also
asm can't be recompiled on the PPC to get you ~4 times speed improvement
going native instead of interpreted.
>Now, I would imagine that C can get closer to assembly depending on the
>task that is being done....what tasks would those be?
Small, simple, processor intensive things can be done more more quickly
in asm (eg BlockMove, Character translation (ISO<->Mac, <crlf><-><cr>,
BinHex/UU translation, etc)). Large things are better written in a high
level language for the reasons stated above (easier to improve the
algorithm, easier to compile on faster machines) (not to mention all the
other obvious advantages (portability (kinda ;-), maintenance (kinda ;-),
etc).
>What's the best way to optimize C?
Don't use any pointers. Pointers screw up optimizing compilers.
>And....which compiler (MPW C, Symantec C, or Metrowerks C) do you think
>produces the fastest C code (with all optimization turned on)? Which do
>you think produces the best quality code (if being the fastest doesn't
>make it the best quality by default)?
No idea, they are probably all withing 10% (as is Pascal, normally on
the faster side).
Peter.
--
Peter N Lewis <peter.lewis@info.curtin.edu.au> Ph: +61 9 368 2055
+++++++++++++++++++++++++++
>From resnick@cogsci.uiuc.edu (Pete Resnick)
Date: Mon, 28 Feb 1994 22:25:15 -0600
Organization: University of Illinois at Urbana-Champaign
In article <2kueq8$865@ncrpda.curtin.edu.au>, peter@ncrpda.curtin.edu.au
(Peter N Lewis) wrote:
>>What's the best way to optimize C?
>
>Don't use any pointers. Pointers screw up optimizing compilers.
What?!?! Sometimes using pointers is the only way to get a really stupid
compiler to do register allocation and register loading properly.
pr
--
Pete Resnick (...so what is a mojo, and why would one be rising?)
Graduate assistant - Philosophy Department, Gregory Hall, UIUC
System manager - Cognitive Science Group, Beckman Institute, UIUC
Internet: resnick@cogsci.uiuc.edu
+++++++++++++++++++++++++++
>From ari@world.std.com (Ari I Halberstadt)
Date: Tue, 1 Mar 1994 07:17:57 GMT
Organization: The World Public Access UNIX, Brookline, MA
In article <NEERI.94Feb28180512@yggdrasil.ethz.ch>,
Matthias Neeracher <neeri@iis.ee.ethz.ch> wrote:
> - Almost all code (with a few exceptions) takes longer to write, debug, and
> maintain in Assembler. Note that for the same reasons, C++ is also faster
> than C, Eiffel is faster than C++, and Perl for some tasks is much faster
> than all of them.
If only Eiffel were more widely available (like, for the mac), and a
bit cheaper for us poorer programmers. Five years ago I fell in love
with Eiffel, but it's still not on the mac (except for A/UX), which
makes it a bit slower than C or C++.
--
Ari Halberstadt ari@world.std.com #include <std/disclaimer.h>
"These beetles were long considered to be very rare because very few
entomologists look for beetles in the mountains, in winter, at night,
during snow storms." -- Purves W. K., et al, "Life: The Science of
+++++++++++++++++++++++++++
>From jim@brunner.wf.com (Jim Brunner)
Date: 28 Feb 94 14:57:34 GMT
Organization: (none)
In article <2kt339$589@ilink1.i-link.com>, you write:
>
> OK, I've heard both sides of the story here...some developers say that C
> can be as fast as assembler (or at least very, very close), provided it
is
> written well enough. Other say that C code doesn't get anywhere near the
> speed of assembler, no matter how it's written.
>
> Now, I would imagine that C can get closer to assembly depending on the
> task that is being done....what tasks would those be?
>
> What's the best way to optimize C?
The best way to optimize ANY program in ANY language is to take a hard look
at the algorithms in use. For almost any program with noticable
performance problems, 90% better speed is all in the algorithm. It's only
when you get down to those last few tweeks for fractions of a percent that
assembler *might* make any difference. (Of course, I'm talking in the
general case - like the original poster. There are, of course,
exceptions.)
Try profiling your code. Run your program with a profiler (like the one
included with Think C) and find out where it's spending it's time. Most
likely, 90% of the time will be in 10% of the code. Look at that 10% and
ignore the rest. Look at the algorithms first - searching a linked list
instead of a binary tree?
Make a decision: How many people does this affect, how critical is it? If
the program in question isn't very critical, it might be more cost
effective to ignore the problem. If not too many people use the program,
it may be more cost effective to buy a faster machine. Assembly language
is expensive. It's expensive in programmer time and maintenance cost.
Go further only for those few lines of highly critical code - realize that
these changes are not necessarily beneficial across platforms. Start by
disassembling the code generated by the C compiler. Take a look at how
slight coding changes affect the generated code.
Only on highly critical sections of code (counting clock cycles here), go
to assembler and hand code the critical section (if the compiler didn't do
it well enough to begin with.
These days, assembler code is almost extinct. I've seen it used recently
on a small subroutine that was part of the firmware running on a DSP chip -
there was a timing limitation in # of clock cycles.
- -
Jim Brunner (jim@brunner.wf.com)
+++++++++++++++++++++++++++
>From gregor@nrlfs1.nrl.navy.mil (joe gregor)
Date: Tue, 1 Mar 1994 14:29:37 GMT
Organization: NRL
In Article <2kueq8$865@ncrpda.curtin.edu.au>, peter@ncrpda.curtin.edu.au
(Peter N Lewis) wrote:
>C or Pascal produce about teh same quality code. It's generally about
>half the speed of reasonably tight assembly code...
>>And....which compiler (MPW C, Symantec C, or Metrowerks C) do you think
>>produces the fastest C code (with all optimization turned on)? Which do
>>you think produces the best quality code (if being the fastest doesn't
>>make it the best quality by default)?
>
>No idea, they are probably all withing 10% (as is Pascal, normally on
>the faster side).
I had always heard/read that C was the fastest language next to asm.
I *never* heard/read that Pascal was even close, let alone faster. Please
identify your references so I may (re)educate myself.
-- Joe
________________________________________________________________________________
Joseph Gregor |
gregor@ccf.nrl.navy.mil | THIS SPACE INTENTIONALLY LEFT BLANK.
tmh@eng.umd.edu |
________________________________|_______________________________________________
+++++++++++++++++++++++++++
>From jwbaxter@olympus.net (John W. Baxter)
Date: Tue, 01 Mar 1994 08:35:48 -0800
Organization: Internet for the Olympic Peninsula
In article <9402281957344983@brunner.wf.com>, jim@brunner.wf.com (Jim
Brunner) wrote:
> Go further only for those few lines of highly critical code - realize that
> these changes are not necessarily beneficial across platforms.
Keeping in mind that "across platforms" above in some cases includes
differences among the 68000, 68020, 68030, and 68040. You may have to
decide which of those you want to target (probably 68040 these days, say I
who still runs a 68030), at the cost of hurting the others.
--
John Baxter Port Ludlow, WA, USA [West shore, Puget Sound]
jwbaxter@pt.olympus.net
+++++++++++++++++++++++++++
>From mmorgan@gpu.srv.ualberta.ca (Martin Morgan)
Date: 1 Mar 1994 17:31:22 GMT
Organization: University of Alberta
Peter N Lewis (peter@ncrpda.curtin.edu.au) wrote:
: mfi@i-link.com (MicroFrontier Inc.) writes:
: >What's the best way to optimize C?
: Don't use any pointers. Pointers screw up optimizing compilers.
Is this true? Is it true in a more restricted sense, don't use pointers in
speed-critical sections of code?
Martin Morgan
University of Alberta
+++++++++++++++++++++++++++
>From nagle@netcom.com (John Nagle)
Date: Tue, 1 Mar 1994 18:40:47 GMT
Organization: NETCOM On-line Communication Services (408 241-9760 guest)
mfi@i-link.com (MicroFrontier Inc.) writes:
>OK, I've heard both sides of the story here...some developers say that C
>can be as fast as assembler (or at least very, very close), provided it is
>written well enough. Other say that C code doesn't get anywhere near the
>speed of assembler, no matter how it's written.
Depends on the compiler. Both MPW C and Symantec C++ are worse than,
say, mainframe FORTRAN compilers of the late 1960s. Good compilers
for the 680x0 machines exist, but not on the Mac. MetaWare High-C
is available for the 68000, but they market it to embedded systems
makers, not Macs. The Sun compiler for the older 68000 Suns were
reasonably good as well, and one large CAD package for the Mac used
to be cross-compiled on a Sun to take advantage of this.
I like to try compiling
int i; char tab1[100]; tab2[100];
for (i=0; i<100; i++) tab1[i] = tab2[i];
and see what the inner loop looks like. Ideally, the inner loop
should have two instructions, but I've seen as many as 12.
Incidentally, using subscripts vs pointer incrementation does not make
much difference with most modern compilers. Even SC++ gets this one
right.
The big SC++ problem is really dumb register usage. One sees
lots of unnecessary register-to-register moves in SC++ output. The
compiler never seems to take full advantage of all the registers
available (it's a port of a compiler for Intel CPUs, which have
fewer registers). In the compiler-design world, using all the registers
effectively is generally considered a win even when not "optimizing",
because it takes less time to figure out which register to use than
to generate the register-to-register moves and stack manipulation
required when doing it wrong. The global optimizer does a good job, though,
except when it makes mistakes.
MPW C has a better code generator but a weaker global optimizer.
I tried this simple test case on a pre-release MetroWerks
compiler, and it generated OK, but not spectacular code.
Still, if there was a compiler for the Mac that generated state of the
art optimized code, programs would be perhaps twice as fast in some cases,
and somewhat smaller.
John Nagle
+++++++++++++++++++++++++++
>From d88-jwa@mumrik.nada.kth.se (Jon Wdtte)
Date: 1 Mar 1994 23:13:52 GMT
Organization: Royal Institute of Technology, Stockholm, Sweden
>>>What's the best way to optimize C?
>>Don't use any pointers. Pointers screw up optimizing compilers.
>What?!?! Sometimes using pointers is the only way to get a really stupid
>compiler to do register allocation and register loading properly.
Yes, but at the same time, pointers (and especially when assigned to
addresses of local variables) can limit more sophisticated compilers,
since they can't do a full analysis of where your pointer might point
and what short-cuts it can take.
--
-- Jon W{tte, h+@nada.kth.se, Mac Hacker Deluxe --
Cookie Jar: Vanilla Yoghurt with Crushed Oreos.
+++++++++++++++++++++++++++
>From resnick@cogsci.uiuc.edu (Pete Resnick)
Date: Tue, 01 Mar 1994 17:32:34 -0600
Organization: University of Illinois at Urbana-Champaign
In article <2l0i7g$o51@news.kth.se>, d88-jwa@mumrik.nada.kth.se (Jon Wtte)
wrote:
>>What?!?! Sometimes using pointers is the only way to get a really stupid
>>compiler to do register allocation and register loading properly.
>
>Yes, but at the same time, pointers (and especially when assigned to
>addresses of local variables) can limit more sophisticated compilers,
>since they can't do a full analysis of where your pointer might point
>and what short-cuts it can take.
Compilers are generally stupid. If you disassemble code resources you'll
see that MPW C is stupider than THINK C, but THINK C is pretty stupid too.
I am waiting for someone to release a compiler that does peep-hole
optimization. Does anyone by any chance know if MetroWorks does so?
Here's a rash claim (flames against my ignorance welcome): Stupid
compilers are why RISC processors do better than CISC processors. If
compilers were smart enough to take advantage of all of the interesting
addressing modes and instructions on CISC architectures, CISCs would
overall be faster at running programs than RISCs. (*Duck*)
pr
--
Pete Resnick (...so what is a mojo, and why would one be rising?)
Graduate assistant - Philosophy Department, Gregory Hall, UIUC
System manager - Cognitive Science Group, Beckman Institute, UIUC
Internet: resnick@cogsci.uiuc.edu
+++++++++++++++++++++++++++
>From platypus@cirrus.som.cwru.edu (Gary Kacmarcik)
Date: 02 Mar 1994 01:25:16 GMT
Organization: Case Western Reserve University, Cleveland, Ohio (USA)
In article <2kvu5a$b06@quartz.ucs.ualberta.ca> mmorgan@gpu.srv.ualberta.ca (Martin Morgan) writes:
Peter N Lewis (peter@ncrpda.curtin.edu.au) wrote:
: mfi@i-link.com (MicroFrontier Inc.) writes:
: >What's the best way to optimize C?
: Don't use any pointers. Pointers screw up optimizing compilers.
Is this true? Is it true in a more restricted sense, don't use pointers in
speed-critical sections of code?
using pointers does NOT directly result in slower code. there are many
cases where pointers can be used to generate significantly optimized
code.
however, if you use pointers you should be aware of the fact that the
code optimizer now can make fewer assumptions about your code, and
thus it may not be able to apply certain optimizations.
get a good book on compiler writing (eg: Aho, Sethi & Ullman) and
read the sections on optimizing. understanding how optimizers work
will greatly aid your programming: you'll have a better understanding
of what the compiler can annd cannot do.
-gary j kacmarcik
platypus@curie.ces.cwru.edu
+++++++++++++++++++++++++++
>From siegel@netcom.com (Rich Siegel)
Date: Wed, 2 Mar 1994 05:41:38 GMT
Organization: Bare Bones Software
In article <resnick-010394173234@colt-17.slip.uiuc.edu> resnick@cogsci.uiuc.edu (Pete Resnick) writes:
>
>Compilers are generally stupid. If you disassemble code resources you'll
>see that MPW C is stupider than THINK C, but THINK C is pretty stupid too.
>I am waiting for someone to release a compiler that does peep-hole
>optimization. Does anyone by any chance know if MetroWorks does so?
Metrowerks does. So does THINK C. So does MPW C.
>Here's a rash claim (flames against my ignorance welcome): Stupid
>compilers are why RISC processors do better than CISC processors. If
>compilers were smart enough to take advantage of all of the interesting
>addressing modes and instructions on CISC architectures, CISCs would
>overall be faster at running programs than RISCs. (*Duck*)
I have a reality adjustment for you. On the 68020, many of the fancy
addressing modes are either a wash or are actually slower than an
equivalent sequence of instructions using 68000-only addressing modes.
R.
--
Rich Siegel % siegel@netcom.com % Principal, Bare Bones Software
--> For information about BBEdit, finger bbedit@world.std.com <--
"He then proceeded to give a history of the universe, in real time."
+++++++++++++++++++++++++++
>From peter@ncrpda.curtin.edu.au (Peter N Lewis)
Date: 2 Mar 1994 13:20:52 +0800
Organization: NCRPDA, Curtin University
>From: chewy@shell.portal.com (Paul Snively)
>...
>q = *p++;
>...
>q = *p++;
>...
>
>Note that the above code features common subexpressions (in fact, for
No, they are not cse's. To be eleigable for cse elemination, the
expression must not have any side effects. I'd quote chapter and verse
out of the Dragon book, but I don't have it handy.
>The moral of the story is twofold: a) try to write clean, readable code
>that doesn't rely on nasty compound functions, especially with
>side-effects; and b) know thy optimizer. If you need help, disassemble
>the code and see what your optimizer is doing behind your back.
No, a) is certainly true, but b) should not be. The optimizer should
never change the way your program behaves - if it does, either the optimizer
is broken (like the THINK C optimizer), or your program is broken.
>From: gregor@nrlfs1.nrl.navy.mil (joe gregor)
>>No idea, they are probably all withing 10% (as is Pascal, normally on
>>the faster side).
> I had always heard/read that C was the fastest language next to asm.
>I *never* heard/read that Pascal was even close, let alone faster. Please
>identify your references so I may (re)educate myself.
You've probably heard thousands of people tell you PCs are better than Macs.
Try it and see for yourself. Pascal compilers will generally produce faster
code than C compilers with equivalent source. Obviously, compilers vary
a great deal, but the above is generally true. I wouldn't worry though,
I expect the next generation of compilers will make C faster than Pascal,
since Pascal compilers will get a lot less work done on them. Of course,
then everyone will be using C++ and efficiency will be thrown right out
the window, but such is life ;-)
>From: mmorgan@gpu.srv.ualberta.ca (Martin Morgan)
>: Don't use any pointers. Pointers screw up optimizing compilers.
>
>Is this true? Is it true in a more restricted sense, don't use pointers in
>speed-critical sections of code?
What I said is true, in that pointers screw up most really clever high
level optimizations because the compiler has an impossible task
of figuring out what you're doing. For example, if you do this:
x = 5;
for i:=1 to 100 do
arr[i] = 0;
end-for;
y = x;
(equivalent in C or Pascal). It is easy for the compiler to know that
x has remained unchanged, that i is now undefined (and thus the
register can be reused), that the array has been modified, that i
is always between 1 and 100 and so no range checking needs to be done,
that y can be assigned 5 directly, etc.
If you instead do this:
x=5;
i=100;
p = @arr[1];
while (i>0) do
*p++ = 0;
i--;
end-while
y = x;
Now it is nearly impossible for the compiler to determine any of that.
It has to be really clever to figure out that p only ever points to
the array arr (a compiler would probably be allowed to assume this
though, since it is undefined what happens if you increment a ptr outside
of the area it started in). If the compiler can't figure that out, then
all variables must be in memory (not registers) and all are potentially
modified, so none of the optimizations above are available.
Of course I wouldn't worry about this either, since most compilers don't
do very much in the way of clever optimizing (and when they try, they
usually screw it up)...
Peter.
--
Peter N Lewis <peter.lewis@info.curtin.edu.au> Ph: +61 9 368 2055
+++++++++++++++++++++++++++
>From resnick@cogsci.uiuc.edu (Pete Resnick)
Date: Wed, 02 Mar 1994 00:51:17 -0600
Organization: University of Illinois at Urbana-Champaign
In article <siegelCM0vtF.9F@netcom.com>, siegel@netcom.com (Rich Siegel) wrote:
>In article <resnick-010394173234@colt-17.slip.uiuc.edu> resnick@cogsci.uiuc.edu (Pete Resnick) writes:
>>
>>Compilers are generally stupid. If you disassemble code resources you'll
>>see that MPW C is stupider than THINK C, but THINK C is pretty stupid too.
>>I am waiting for someone to release a compiler that does peep-hole
>>optimization. Does anyone by any chance know if MetroWorks does so?
>
>Metrowerks does. So does THINK C. So does MPW C.
Surely you're kidding. I've seen MPW C move things back and forth between
the same two registers (or worse, to and from the stack) oodles of times
in a series of instructions with no other side effects. THINK C constantly
does 'MOVE.L (A7)+,D3' followed by a 'TST.L D3' followed by a branch on
condition code. And I've never seen either of them generate a DBcc
instruction, even when I force feed it; I have lots of code for which
THINK C generates:
SUBQ.W #$1,D3
CMPI.W #$FFFF,D3
BNE.S *-$000C
What *are* they looking for if not these kinds of things?
As for the RISC/CISC argument I started, I've gotten lots of really cool
mail in response, some in support and some against, but almost all of it
saying, "It's a lot more complicated than you think." I figured as much,
but I do thank everyone for their comments; I have learned a lot in the
process.
pr
--
Pete Resnick (...so what is a mojo, and why would one be rising?)
Graduate assistant - Philosophy Department, Gregory Hall, UIUC
System manager - Cognitive Science Group, Beckman Institute, UIUC
Internet: resnick@cogsci.uiuc.edu
+++++++++++++++++++++++++++
>From d88-jwa@mumrik.nada.kth.se (Jon Wdtte)
Date: 2 Mar 1994 10:32:23 GMT
Organization: Royal Institute of Technology, Stockholm, Sweden
>I don't have my ANSI reference in front of me, but I distinctly recall
>my shock upon reading something in it that made it quite clear that the
>semantics of your program could differ between unoptimized and
>optimized versions of your code.
So far so good.
>To give just one obvious example of how this could happen, consider a
>function that uses a pointer p, and contains code like this:
>q = *p++;
>q = *p++;
>let's say I compile this code without Common Subexpression Elimination.
> The pointer gets incremented twice, which is probably what the author
>had in mind. But if I compile with Common Subexpression Elimination
>on, the compiler is completely free to evaluate the p++ once and stick
>the result in a register. Oops.
No, that's NOT legal, since this has a very well-defined semantic
meaning. What the compiler CAN do, is change its behaviour for
UNDEFINED cases, such as:
foo ( q ++ , q ++ ) ;
Where foo might be called as foo ( 0 , 1 ) or foo ( 1 , 0 ) depending
on moon phase. Anyway, since your program shouldn't be relying on
such UNDEFINED behaviour, the above allowance really isn't a problem.
And since we all validate our code and use ASSERTs everywhere and
step through it at the instruction level to verify it works right
after we wrote it (using all available documentation) this group
shouldn't have any "help me with my bug" questions either :-) :-)
--
-- Jon W{tte, h+@nada.kth.se, Mac Hacker Deluxe --
"It was, in fact, cool as all get-out. Fortunately it was a little
too late (historically speaking) to be groovy."
-- Dennis Pelton
+++++++++++++++++++++++++++
>From infosafe@panix.com (Infosafe Systems)
Date: 2 Mar 1994 11:28:02 -0500
Organization: PANIX Public Access Internet and Unix, NYC
In article <siegelCM0vtF.9F@netcom.com>, Rich Siegel <siegel@netcom.com> wrote:
>In article <resnick-010394173234@colt-17.slip.uiuc.edu>
resnick@cogsci.uiuc.edu (Pete Resnick) writes:
>>Here's a rash claim (flames against my ignorance welcome): Stupid
^^^^^^
>>compilers are why RISC processors do better than CISC processors. If
^^^ ^^^ ^^^^ ^^ ^^^^^^ ^^^^ ^^^^
>>compilers were smart enough to take advantage of all of the interesting
>>addressing modes and instructions on CISC architectures, CISCs would
>>overall be faster at running programs than RISCs. (*Duck*)
I'm no expert but perhaps someone here could help me out. A few months
ago I read a longish article in Byte? (I will post the reference
tomorrow when I am in work, if anyone is interested) about the greatness
of the MPC chip.
One of the topics it discussed in detail was the fact that RISC chips have
become popular, and more powerful than CISC chips for a bunch of reasons.
These included fixed instruction length to eliminate bubbles in the
pipeline, faster instruction decode because you don't have to spend time
figuring out how long your instruction is, etc.
The last point that they made was that RISC has "come out on top" *because*
of improvements in compiler technology. The article said that optimizers
were able to make better use of RISC instructions than CISC instructions,
and this has been one of the motivating forces in developing RISC chips
for workstations, where you have *good* compilers ;-)
Opinions? Let the flames begin!
(Again, I will post the article and a better summary, if anyone is interested)
Bradford Smith
+++++++++++++++++++++++++++
>From siegel@netcom.com (Rich Siegel)
Date: Wed, 2 Mar 1994 16:06:46 GMT
Organization: Bare Bones Software
In article <resnick-020394005117@colt-42.slip.uiuc.edu> resnick@cogsci.uiuc.edu (Pete Resnick) writes:
>In article <siegelCM0vtF.9F@netcom.com>, siegel@netcom.com (Rich Siegel) wrote:
>
>>In article <resnick-010394173234@colt-17.slip.uiuc.edu> resnick@cogsci.uiuc.edu (Pete Resnick) writes:
>>>
>>>Compilers are generally stupid. If you disassemble code resources you'll
>>>see that MPW C is stupider than THINK C, but THINK C is pretty stupid too.
>>>I am waiting for someone to release a compiler that does peep-hole
>>>optimization. Does anyone by any chance know if MetroWorks does so?
>>
>>Metrowerks does. So does THINK C. So does MPW C.
>
>Surely you're kidding. I've seen MPW C move things back and forth between
>the same two registers (or worse, to and from the stack) oodles of times
>in a series of instructions with no other side effects. THINK C constantly
>does 'MOVE.L (A7)+,D3' followed by a 'TST.L D3' followed by a branch on
>condition code. And I've never seen either of them generate a DBcc
>instruction, even when I force feed it; I have lots of code for which
>THINK C generates:
>
> SUBQ.W #$1,D3
> CMPI.W #$FFFF,D3
> BNE.S *-$000C
>
>What *are* they looking for if not these kinds of things?
I'm not kidding, and don't call me Shirley. :-) Don't confuse
instruction selection and target analysis with peepholing, and DBRA is
not a cure-all. One thing that THINK C (and THINK Pascal) do pretty
well is branch-and-loop optimization (a "peephole" operation).
All of the above-mentioned compilers do -some- peepholing. It may not
be as thorough as you might like it, but it's done.
R.
--
Rich Siegel % siegel@netcom.com % Principal, Bare Bones Software
--> For information about BBEdit, finger bbedit@world.std.com <--
"...yeah, I inhaled, and then I drank the bong water. So what're
you gonna do about it?" - Dennis Miller, on Bill Clinton
+++++++++++++++++++++++++++
>From ari@world.std.com (Ari I Halberstadt)
Date: Wed, 2 Mar 1994 17:00:16 GMT
Organization: The World Public Access UNIX, Brookline, MA
In article <resnick-020394005117@colt-42.slip.uiuc.edu>,
Pete Resnick <resnick@cogsci.uiuc.edu> wrote:
>condition code. And I've never seen either of them generate a DBcc
>instruction, even when I force feed it; I have lots of code for which
>THINK C generates:
>
> SUBQ.W #$1,D3
> CMPI.W #$FFFF,D3
> BNE.S *-$000C
>
>What *are* they looking for if not these kinds of things?
Try structure assignment in THINK C. The structure has to be big
enough, or the compiler will just use word or long word move
instructions. Here's an example of a DBF instruction:
static void x(void)
{
struct { long a, b, c, d, e, f, g; } a, b;
a = b;
}
x:
00000000 LINK A6,#$FFC8
00000004 LEA $FFE4(A6),A0
00000008 LEA $FFC8(A6),A1
0000000C MOVEQ #$06,D0
0000000E MOVE.L (A1)+,(A0)+
00000010 DBF D0,*-$0002 ; 0000000E
00000014 UNLK A6
00000016 RTS
0000001C
--
Ari Halberstadt ari@world.std.com #include <std/disclaimer.h>
"These beetles were long considered to be very rare because very few
entomologists look for beetles in the mountains, in winter, at night,
during snow storms." -- Purves W. K., et al, "Life: The Science of
+++++++++++++++++++++++++++
>From jwbaxter@olympus.net (John W. Baxter)
Date: Wed, 02 Mar 1994 10:03:00 -0800
Organization: Internet for the Olympic Peninsula
In article <2l2eqi$j40@panix2.panix.com>, infosafe@panix.com (Infosafe
Systems) wrote:
> I'm no expert but perhaps someone here could help me out. A few months
> ago I read a longish article in Byte? (I will post the reference
> tomorrow when I am in work, if anyone is interested) about the greatness
> of the MPC chip.
>
> One of the topics it discussed in detail was the fact that RISC chips have
> become popular, and more powerful than CISC chips for a bunch of reasons.
> These included fixed instruction length to eliminate bubbles in the
> pipeline, faster instruction decode because you don't have to spend time
> figuring out how long your instruction is, etc.
>
> The last point that they made was that RISC has "come out on top" *because*
> of improvements in compiler technology. The article said that optimizers
> were able to make better use of RISC instructions than CISC instructions,
> and this has been one of the motivating forces in developing RISC chips
> for workstations, where you have *good* compilers ;-)
I've been around these crazy machines since around 1959 (more like 1952 if
I get to count helping mother with her "homework" with her computer usage
at JPL (she used IBM 650, ElectroData <<became part of Burroughs>> #1, IBM
704)).
There have been periodic waves of RISCness, followed by retreats to
CISCness. But the R is gradually winning...each retreat to the C direction
goes a little less far.
I'm beginning to thing that the current RISC wave is the real thing, and
that there won't be much retreat. And I tend to agree that the advances in
compiler technology are a major reason why RISC may well happen this time.
In any case, as viewed from the late 1950s, everything we run today is
RISC. Consider the NCR 304: 3-address instructions (add A to B putting
the result in C). One of the interesting single machine instructions was
"write-copy-read": write this record to that tape, read records from that
other tape and copy them to that tape until one has a key which matches
this test, and give me the matching record. Absolutely perfect for
father-son file updates, which aren't done much any more.
The 304 also had single instruction in-memory sorts and merges.
--
John Baxter Port Ludlow, WA, USA [West shore, Puget Sound]
jwbaxter@pt.olympus.net
+++++++++++++++++++++++++++
>From mxmora@unix.sri.com (Matt Mora)
Date: 2 Mar 1994 11:10:40 -0800
Organization: SRI International, Menlo Park, CA
In article <resnick-010394173234@colt-17.slip.uiuc.edu> resnick@cogsci.uiuc.edu (Pete Resnick) writes:
>Here's a rash claim (flames against my ignorance welcome): Stupid
>compilers are why RISC processors do better than CISC processors. If
>compilers were smart enough to take advantage of all of the interesting
>addressing modes and instructions on CISC architectures, CISCs would
>overall be faster at running programs than RISCs. (*Duck*)
I don't think could be possible. Even though its called RISC the PowerPC
chip has more instructions than the 68020 or so I've read. Its the
complexity of the instruction that matters. An instuction on a RISC takes at
max 5 clocks, but on a CISC who knows how long a certain intruction
will take. There goes your pipelining.
The beauty of RISC is its simplicity. With few transistors and less
logic, its easy to get faster CPU speeds. That's why even before the
first PowerPc mac shipped, its already be upgraded from 66 mhz to 80 mhz.
A slower running CISC will never be able to keep up. Remember the 32k
of on chip cache takes up a big chuck of the die size. Without the cache
the die would be even smaller. (but slower) CISC is doomed because
the art of writing tight fast code is becoming obsolete. If compiler
writers won't do it why should we. Image how fast things would be on RISC
with hand tuned assembly.
Xavier
--
___________________________________________________________
Matthew Xavier Mora Matt_Mora@qm.sri.com
SRI International mxmora@unix.sri.com
333 Ravenswood Ave Menlo Park, CA. 94025
+++++++++++++++++++++++++++
>From nagle@netcom.com (John Nagle)
Date: Wed, 2 Mar 1994 19:30:41 GMT
Organization: NETCOM On-line Communication Services (408 241-9760 guest)
siegel@netcom.com (Rich Siegel) writes:
>In article <resnick-010394173234@colt-17.slip.uiuc.edu> resnick@cogsci.uiuc.edu (Pete Resnick) writes:
>>Compilers are generally stupid. If you disassemble code resources you'll
>>see that MPW C is stupider than THINK C, but THINK C is pretty stupid too.
>>I am waiting for someone to release a compiler that does peep-hole
>>optimization. Does anyone by any chance know if MetroWorks does so?
>Metrowerks does. So does THINK C. So does MPW C.
But SC++ doesn't, judging from the code.
>>Here's a rash claim (flames against my ignorance welcome): Stupid
>>compilers are why RISC processors do better than CISC processors. If
>>compilers were smart enough to take advantage of all of the interesting
>>addressing modes and instructions on CISC architectures, CISCs would
>>overall be faster at running programs than RISCs. (*Duck*)
>I have a reality adjustment for you. On the 68020, many of the fancy
>addressing modes are either a wash or are actually slower than an
>equivalent sequence of instructions using 68000-only addressing modes.
That's a problem with many machines with variable-length
instructions. Check the timings for the 68030 and '040, though;
the ratios get better as you throw more transistors at the problem.
John Nagle
+++++++++++++++++++++++++++
>From jvp@tools1.ee.iastate.edu (Jim Van Peursem)
Date: 2 Mar 94 21:24:34 GMT
Organization: Iowa State University, Ames, Iowa
In <2l2obg$fca@unix.sri.com> mxmora@unix.sri.com (Matt Mora) writes:
>In article <resnick-010394173234@colt-17.slip.uiuc.edu> resnick@cogsci.uiuc.edu (Pete Resnick) writes:
>>Here's a rash claim (flames against my ignorance welcome): Stupid
>>compilers are why RISC processors do better than CISC processors. If
>>compilers were smart enough to take advantage of all of the interesting
>>addressing modes and instructions on CISC architectures, CISCs would
>>overall be faster at running programs than RISCs. (*Duck*)
>I don't think could be possible. Even though its called RISC the PowerPC
>chip has more instructions than the 68020 or so I've read. Its the
>complexity of the instruction that matters. An instuction on a RISC takes at
>max 5 clocks, but on a CISC who knows how long a certain intruction
>will take. There goes your pipelining.
Ah yes, the wandering definition of RISC. I saw a nice summary of
what RISC means in comp.arch awhile back. It's more a function of
cycles-per-instruction and number of registers, etc than the number
of instructions supported.
I agree with Pete that originally, RISC was driven by the fact that
most compilers simply didn't support the complex instructions in some
chips. But more accurately, some complex instructions in some chips were
slower than their counter-part simple instructions to perform the same
task. The VAX had several of these as I recall. Anyway, your definition
of RISC taking a max 5 clock cycles is wrong. That depends on the depth
of the pipe and other factors.
>The beauty of RISC is its simplicity. With few transistors and less
>logic, its easy to get faster CPU speeds. That's why even before the
>first PowerPc mac shipped, its already be upgraded from 66 mhz to 80 mhz.
But these days, the RISC processors have around the same number of
transistors as their CISC counterparts. It's more a function of the
regularity of the instructions. Since all instructions are the same
size, and decode the same, it's easy to pipeline them and keep the
pipe full.
I say the reason RISC is winning the game now is because of the
advancements in both the pipelines and compilers.
>Image how fast things would be on RISC
>with hand tuned assembly.
It would be slower. :) Remembering all of the pipeline hazards
by hand is very complex. A compiler can do a much better job of
these kinds of scheduling issues for any reasonably sized routine.
+---------------------------------------------------------------+
| Jim Van Peursem - Ph.D. Candidate - Ham Radio -> KE0PH |
| Department of Electrical Engineering and Computer Engineering |
| Iowa State University - Ames, IA 50011 : (515) 294-8339 |
| internet - jvp@iastate.edu -or- jvp@cpre1.ee.iastate.edu |
+---------------------------------------------------------------+
+++++++++++++++++++++++++++
>From jim@brunner.wf.com (Jim Brunner)
Date: 2 Mar 94 02:57:28 GMT
Organization: (none)
In article <resnick-010394173234@colt-17.slip.uiuc.edu>, you write:
>
> Here's a rash claim (flames against my ignorance welcome): Stupid
> compilers are why RISC processors do better than CISC processors. If
> compilers were smart enough to take advantage of all of the interesting
> addressing modes and instructions on CISC architectures, CISCs would
> overall be faster at running programs than RISCs. (*Duck*)
Actually, good RISC compilers are MORE difficult because of the difficulty
of doing pipeline optimization.
- -
Jim Brunner (jim@brunner.wf.com)
+++++++++++++++++++++++++++
>From jtbell@cs1.presby.edu (Jon Bell)
Date: Wed, 2 Mar 94 23:06:40 GMT
Organization: Presbyterian College, Clinton, South Carolina USA
In article <gregor.1112919817C@ra.nrl.navy.mil>,
joe gregor <gregor@nrlfs1.nrl.navy.mil> wrote:
>In Article <2kueq8$865@ncrpda.curtin.edu.au>, peter@ncrpda.curtin.edu.au
>(Peter N Lewis) wrote:
>
>>C or Pascal produce about teh same quality code. It's generally about
>>half the speed of reasonably tight assembly code...
>
> I had always heard/read that C was the fastest language next to asm.
>I *never* heard/read that Pascal was even close, let alone faster. Please
>identify your references so I may (re)educate myself.
It makes no sense to talk about the "speed" of a language (or rather, its
compiled code) without reference to the compiler and the computer it's
running on. There is nothing intrinsic in the design of Pascal or C that
would make one faster than the other. What counts is the implementation.
On some computers, C is indeed much faster than Pascal because their C
compilers are more "efficient" in that respect than their Pascal
compilers. On the Mac, this is not the case. The two languages run just
about neck and neck when you compare (say) Think Pascal with Think C or
MPW Pascal with MPW C.
I don't have specific references handy, but I'll browse through my back
issues of MacTutor and see if I can find something to post if no one beats
me to it.
--
Jon Bell <jtbell@presby.edu> Presbyterian College
Dept. of Physics and Computer Science Clinton, South Carolina USA
+++++++++++++++++++++++++++
>From especkma@reed.edu (Erik A. Speckman)
Date: 3 Mar 1994 06:56:45 GMT
Organization: Hellmouth-Heater Democrat
In article <jvp.762643474@tools1.ee.iastate.edu>,
Jim Van Peursem <jvp@tools1.ee.iastate.edu> wrote:
> I agree with Pete that originally, RISC was driven by the fact that
>most compilers simply didn't support the complex instructions in some
>chips. But more accurately, some complex instructions in some chips were
>slower than their counter-part simple instructions to perform the same
>task. The VAX had several of these as I recall. Anyway, your definition
>of RISC taking a max 5 clock cycles is wrong. That depends on the depth
>of the pipe and other factors.
No, no, no its that implimenting complex instructions costs silicon that
could be better used increacing pipeline complexity or chache and
speeding up all operations.
No, its a desert topping.
No, it is all those things and a desert topping to boot.
>
--
____________________________________________________________________________
Erik Speckman especkma@romulus.reed.edu GBDS
Workstation- A high-performance microcomputer designed to run benchmarks.
+++++++++++++++++++++++++++
>From rang@winternet.mpls.mn.us (Anton Rang)
Date: 03 Mar 1994 14:37:47 GMT
Organization: Minnesota Angsters
In article <resnick-280294222515@colt-19.slip.uiuc.edu> resnick@cogsci.uiuc.edu (Pete Resnick) writes:
>In article <2kueq8$865@ncrpda.curtin.edu.au>, peter@ncrpda.curtin.edu.au
>(Peter N Lewis) wrote:
>
>>>What's the best way to optimize C?
>>
>>Don't use any pointers. Pointers screw up optimizing compilers.
>
>What?!?! Sometimes using pointers is the only way to get a really stupid
>compiler to do register allocation and register loading properly.
Yes, but if you have a really *smart* compiler, pointers screw it up
royally, especially if you are passing parameters around by address.
Once you take the address of an object, almost any access through a
pointer stops the compiler from being able to optimize it. So you're
often better off to use a temporary variable, like --
temp_x = x;
do_something(&temp_x);
x = temp_x;
and keep 'x' local, so the compiler can (a) keep it in a register, and
(b) assume that its value isn't changed by almost *every* call and
every assignment through a pointer.
Of course, using the best algorithms is still the best way to optimize
*any* language.
-- Anton
--
Anton Rang (rang@acm.org)
+++++++++++++++++++++++++++
>From Brad Koehn <koehn@macc.wisc.edu>
Date: 4 Mar 1994 01:58:54 GMT
Organization: University of Wisconsin
In article <2l17nk$1ku@ncrpda.curtin.edu.au> Peter N Lewis,
peter@ncrpda.curtin.edu.au writes:
>Try it and see for yourself. Pascal compilers will generally produce
faster
>code than C compilers with equivalent source. Obviously, compilers vary
>a great deal, but the above is generally true. I wouldn't worry though,
>I expect the next generation of compilers will make C faster than Pascal,
>since Pascal compilers will get a lot less work done on them. Of course,
>then everyone will be using C++ and efficiency will be thrown right out
>the window, but such is life ;-)
Heck, check out the XLC and XLC++ compilers from IBM. Talk about
well-built! From what I understand, Apple was using them for quite a
while to compile for PPC (ahh, MPW, you dog you).
Anyway, these two beasties can do some really nice magic with your code.
And IBM just keeps improving them. Now, if only the Mac had it so good...
Oh, that's right, PowerOpen lets me use both AIX and MAS on the same
machine! So I can use XLC++ with my Mac code! Life is so good!
_________________________________________________________________________
Brad Koehn Data Transformations, Inc. koehn@macc.wisc.edu
+++++++++++++++++++++++++++
>From Brad Koehn <koehn@macc.wisc.edu>
Date: 4 Mar 1994 02:06:09 GMT
Organization: University of Wisconsin
In article <RANG.94Mar3083747@icicle.winternet.mpls.mn.us> Anton Rang,
rang@winternet.mpls.mn.us writes:
> Yes, but if you have a really *smart* compiler, pointers screw it up
>royally, especially if you are passing parameters around by address.
>Once you take the address of an object, almost any access through a
>pointer stops the compiler from being able to optimize it. So you're
>often better off to use a temporary variable, like --
>
> temp_x = x;
> do_something(&temp_x);
> x = temp_x;
>
>and keep 'x' local, so the compiler can (a) keep it in a register, and
>(b) assume that its value isn't changed by almost *every* call and
>every assignment through a pointer.
Can't the compiler just check the code for do_something and see if it
changes temp_x? I realize it would be a real pain for compilers, but so
what? Life is pain. Anyone who tells you otherwise is trying to sell you
something.* Just build a table for each function that checks to see if
the parameters are changed. Sigh. I guess I should have taken that
compiler class...
* The Man in Black, "The Princess Bride"
_________________________________________________________________________
Brad Koehn Data Transformations, Inc. koehn@macc.wisc.edu
+++++++++++++++++++++++++++
>From pottier@prao.ens.fr (Francois Pottier)
Date: 4 Mar 1994 14:26:33 GMT
Organization: Ecole Normale Superieure, PARIS, France
In article <2l652h$aa6@news.doit.wisc.edu>,
Brad Koehn <koehn@macc.wisc.edu> wrote:
>> temp_x = x;
>> do_something(&temp_x);
>> x = temp_x;
>Can't the compiler just check the code for do_something and see if it
>changes temp_x? I realize it would be a real pain for compilers, but so
No, it can't. This looks like a typical undecidable problem. In a language
with pointers like C or Pascal, there are tons of ways of modifying a
variable. For instance, look at this:
long x, y;
long *p;
p = &x;
p++;
*p = 0;
This code modifies y. Hard to tell, uh ?
I think it should be relatively easy to demonstrate that the problem
is undecidable. I could try writing a proof if you wish.
--
Francois Pottier ___ ___ _ _ / ___ ___ ___
pottier@dmi.ens.fr /_ /__/ /_| /| / / / / / / /__
/ / \ / | / |/ /___ /__/ / ___/ _
/
+++++++++++++++++++++++++++
>From mmorgan@gpu.srv.ualberta.ca (Martin Morgan)
Date: 4 Mar 1994 16:02:53 GMT
Organization: University of Alberta
Francois Pottier (pottier@prao.ens.fr) wrote:
: Brad Koehn <koehn@macc.wisc.edu> wrote:
: >> temp_x = x;
: >> do_something(&temp_x);
: >> x = temp_x;
: >Can't the compiler just check the code for do_something and see if it
: >changes temp_x? I realize it would be a real pain for compilers, but so
: No, it can't. This looks like a typical undecidable problem. In a language
or the user declare do_something as do_something (const type-of-x *)?. Is
that a legal declaration?
: variable. For instance, look at this:
: long x, y;
: long *p;
: p = &x;
: p++;
: *p = 0;
: This code modifies y. Hard to tell, uh ?
surely memory allocation of x and y is left to the compiler, so there's no
guarantee that anything relevant to the snippet is modified by *p = 0?
Martin Morgan
+++++++++++++++++++++++++++
>From rang@winternet.mpls.mn.us (Anton Rang)
Date: 05 Mar 1994 15:44:45 GMT
Organization: Minnesota Angsters
In article <2l652h$aa6@news.doit.wisc.edu> Brad Koehn <koehn@macc.wisc.edu> writes:
>> temp_x = x;
>> do_something(&temp_x);
>> x = temp_x;
>
>Can't the compiler just check the code for do_something and see if it
>changes temp_x? I realize it would be a real pain for compilers, but so
>what?
Yes and no. The problem is that C's separate compilation model
calls for "compile a bunch of functions so that they all work
correctly independently; at link time, hook them together." To make
this work right, you need to defer code generation until linking.
There are Ada development systems which do this (they need to generate
extremely tight code for embedded systems).
However, because of C's ubiquitous pointers, this trick only works
for very simple functions. Figuring out what variables a given
procedure call might modify, or even an approximation to it, in the
presence of globals or structures containing pointers, is non-trivial.
--
Anton Rang (rang@acm.org)
+++++++++++++++++++++++++++
>From zstern@adobe.com (Zalman Stern)
Date: Mon, 7 Mar 1994 02:50:34 GMT
Organization: Adobe Systems Incorporated
Anton Rang writes
> Yes and no. The problem is that C's separate compilation model
> calls for "compile a bunch of functions so that they all work
> correctly independently; at link time, hook them together." To make
> this work right, you need to defer code generation until linking.
> There are Ada development systems which do this (they need to generate
> extremely tight code for embedded systems).
MIPS' C compiler/linker and the Plan 9 C compiler/linker (from AT&T Bell
Labs) both offer link time code generation and optimization. I'm sure there
are others. (Part of the problem with discussing a topic like this in the
Mac community is most Mac programmers have limited experience with the broad
realm of tools that run on other platforms.) I'd be happy with a Mac C
compiler that was up to the state-of-the-art with regard to intra-procedure
optimization. (Though I insist on automatic inlining of appropriate file
scope static functions.)
--
Zalman Stern zalman@adobe.com (415) 962 3824
Adobe Systems, 1585 Charleston Rd., POB 7900, Mountain View, CA 94039-7900
"Do right, and risk consequences." Motto of Sam Houston (via Molly Ivins)
+++++++++++++++++++++++++++
>From armb@setanta.demon.co.uk (Alan Braggins)
Date: Mon, 7 Mar 1994 17:22:02 GMT
Organization: Setanta Software
In article <2l7m3d$jil@quartz.ucs.ualberta.ca> mmorgan@gpu.srv.ualberta.ca (Martin Morgan) writes:
: >Can't the compiler just check the code for do_something and see if it
: >changes temp_x? I realize it would be a real pain for compilers, but so
: No, it can't. This looks like a typical undecidable problem. In a language
or the user declare do_something as do_something (const type-of-x *)?. Is
that a legal declaration?
It is. But do_something is allowed to cast away const with
implementation defined results.
--
Alan Braggins armb@setanta.demon.co.uk abraggins@cix.compulink.co.uk
"Any technology distinguishable from magic is insufficiently advanced"
+++++++++++++++++++++++++++
>From peter@ncrpda.curtin.edu.au (Peter N Lewis)
Date: 9 Mar 1994 11:41:15 +0800
Organization: NCRPDA, Curtin University
scott.m.silver@dartmouth.edu (Scott M. Silver) writes:
>All the books I've read about RISC say this is true. I think this is
>from the standpoint that it is also easier to optimize for RISC chips
>because there aren't 9 million addressing modes, and eighty different
>ways to do things.
Yep, it was great writing an optimizing compiler for the ARM (Acorn
RISC Machine) (now used in the Newton). We'd sit down and look at the
code it produced and we could come up with a thousand different ways of
doing the same thing, and they all took exactly the same amount of time!
Very nice. Much more pleasant than sitting down with a 68040 manual and
spending several days comparing timing before deciding that it's non-
deterministic ;-)
Peter.
--
Peter N Lewis <peter.lewis@info.curtin.edu.au> Ph: +61 9 368 2055
+++++++++++++++++++++++++++
>From tom@wcc.oz.au (Tom Evans)
Date: 10 Mar 94 09:05:12 GMT
Organization: Webster Computer Corp, Melbourne, Australia
In article <2kueq8$865@ncrpda.curtin.edu.au>, peter@ncrpda.curtin.edu.au (Peter N Lewis) surprisingly writes:
> mfi@i-link.com (MicroFrontier Inc.) writes:
>
> >And....which compiler (MPW C, Symantec C, or Metrowerks C) do you think
> >produces the fastest C code (with all optimization turned on)? Which do
Don't run MPW C (V3.3) with "-opt full" - it can't even printf() if you do!
> No idea, they are probably all withing 10% (as is Pascal, normally on
> the faster side).
I wish it were so Peter, but it ain't, not unless they're all within
10% of being 30% slower than they should be.
I compile on a Macintosh under MPW and on a Sun 3 under its compiler
or gcc. The Mac is a 33MHz 68030. The Sun is a 20MHz 68020. When I
benchmark them against each other, they always run at about the SAME
SPEED.
The Sun compiles the following:
void testcopy(char *p1, char *p2, short length)
{
while (length--)
*p1++ = *p2++;
}
To:
testcopy: linkw a6,#-0x10
testcopy+4: movl a6@(0xc),a0
testcopy+8: movl a6@(8),a1
testcopy+0xc: movw a6@(0x12),d0
testcopy+0x10: bras _memcpy+0x14
testcopy+0x12: movb a0@+,a1@+
testcopy+0x14: dbra d0,_memcpy+0x12
testcopy+0x18: unlk a6
testcopy+0x1a: rts
This is pretty much exactly as an assembler programmer might do it
(but a real assembler programmer would unroll the loop, as would a
real C programmer :-).
MPW with optimisation on makes the following botch of it:
00000000: LINK A6,#$0000
00000004: MOVEM.L D7/A3/A4,-(A7)
00000008: MOVE.W $0012(A6),D7
0000000C: MOVEA.L $000C(A6),A3
00000010: MOVEA.L $0008(A6),A4
00000014: BRA.S *+$0004 ; 00000018
00000016: MOVE.B (A3)+,(A4)+
00000018: MOVE.W D7,D0
0000001A: SUBQ.W #$1,D7
0000001C: TST.W D0
0000001E: BNE.S *-$0008 ; 00000016
00000020: MOVEM.L -$000C(A6),D7/A3/A4
00000026: UNLK A6
00000028: RTS
MPW has used 42 bytes of code to do what the Sun did in 28 (50% more),
and it takes 40% longer to do it. There are 2 instructions in the
Sun's inner loop, versus 5 with MPW.
Benchmark figures - I copied the Sun's assembler code to the Mac and
assembled it there to get the "Mac running Sun compiled" figure:
To run 100000 loops of the above function with "len = 10" takes:
Sun running Mac running Mac running
Sun compiled Mac compiled Sun compiled
--------------------------------------------
23 s 22 s 15 s
The Mac is 47% faster running the same binary, but only 5% faster
running the same "source". MPW generated code that takes 40% longer
to execute than the Sun-compiled code did.
Yes, this is a slightly contrived example (a - shock, horror,
BENCHMARK!) - it took a tiny amount of work (and knowledge) to get
the Sun to use the DBRA, and not a subtract-and-branch, but at least
it doesn't copy it before comparing.
However, whenever I've looked at MPW's output, I've always seen
unnecessary copying between registers, unnecessary masking, weird
testing, operations that can be done in one line of code taking 4 or
5 lines. I've foung gcc does about the same job as the Sun compiler
does (i.e. very good).
Does this mean that if the Macintosh ROMs and System were recompiled with
gcc the system would be 30% smaller and 50% faster? :-)
> >What's the best way to optimize C?
>
> Don't use any pointers. Pointers screw up optimizing compilers.
MPW doesn't count as an "optimising compiler" then, so it doesn't
matter :-). Use pointers in preference to array references though.
Back to the original question - has anyone compared MPW and Symantec
and Metrowerks (and the latest gnu port perhaps) head-on-head?
Compared code SIZE and SPEED?
========================
Tom Evans tom@wcc.oz.au
Webster Computer Corp P/L, 11 Glenvale Crescent Mulgrave, Melbourne 3170
Victoria, Australia 61-3-560-1100 FAX ...560-0067 A.C.N. 004 818 455
wcc@cup.portal.com, AppleLink: "WEBSTER.USA"
2109 O'Toole Avenue, Suite J. San Jose, CA 95131-1338 USA
1-408-954-8054 FAX 1-408-954-1832 AppleLink WEBSTER.USA
+++++++++++++++++++++++++++
>From peirce@outpost.SF-Bay.org (Michael Peirce)
Date: Thu, 10 Mar 94 09:04:22 PST
Organization: Peirce Software, Inc.
In article <3731@wcc.oz.au> (comp.sys.mac.programmer), tom@wcc.oz.au (Tom Evans) writes:
> Does this mean that if the Macintosh ROMs and System were recompiled with
> gcc the system would be 30% smaller and 50% faster? :-)
You're assuming the "system" is written in C. Parts are, but bigger
parts are written in plain old assembler. Other parts are written
in Pascal.
Some parts are highly hand optomized to run best on the specific processor
they are destine to run on since the code lives in a ROM that won't
ever be plugged into another processor type. BlockMove and CopyBits
come to mind.
I understand major parts of the system are (have been) rewritten in
C to make them portable (to PowerPC and x86).
-- Michael Peirce -- peirce@outpost.sf-bay.org
-- Peirce Software, Inc. -- 719 Hibiscus Place, Suite 301
-- -- San Jose, California USA 95117
-- Makers of: Smoothie & -- voice: +1.408.244.6554 fax: +1.408.244.6882
-- Peirce Print Tools -- AppleLink: peirce & America Online: AFC Peirce
+++++++++++++++++++++++++++
>From s_heidri@irau32.ira.uka.de (Dietmar Heidrich)
Date: 17 Mar 1994 13:39:58 GMT
Organization: University of Karlsruhe, FRG
In article <gregor.1112919817C@ra.nrl.navy.mil>, gregor@nrlfs1.nrl.navy.mil (joe gregor) writes:
|>
|> I had always heard/read that C was the fastest language next to asm.
|> I *never* heard/read that Pascal was even close, let alone faster. Please
|> identify your references so I may (re)educate myself.
The implementation of a language can be fast or slow, not the language itself.
For some reasons not well understood (unless you agree with Richard Gabriel in
his JOOP article), C is widespread used and therefore gets most support efforts
(at least on other platforms).
--
Dietmar Heidrich, Universitaet Karlsruhe, Germany
"Die Hoffnung auf den Tod ist das einzige, was mich am Leben erhaelt."
---------------------------
>From mbayme@bih.harvard.edu (Michael J. Bayme, M.D.)
Subject: Color Terminal Emulator
Date: Sun, 06 Mar 1994 13:37:29 -0500
Organization: Beth Israel Hospital Boston
Hi! I'm writing a color terminal emultor for my hospital's system - and
it's slow. I use srcCopy and lots of DrawChars - it's slow. I've seen tech
notes about a bug in system 7 that makes this sort of code run slowly. Is
this true? Are there work-arounds available.
Thanks, Michael Bayme
+++++++++++++++++++++++++++
>From leonardr@netcom.com (Leonard Rosenthol)
Date: Sun, 6 Mar 1994 20:32:26 GMT
Organization: Aladdin Systems, Inc.
In article <mbayme-060394133729@bayme.bih.harvard.edu>,
mbayme@bih.harvard.edu (Michael J. Bayme, M.D.) wrote:
> Hi! I'm writing a color terminal emultor for my hospital's system - and
> it's slow. I use srcCopy and lots of DrawChars - it's slow. I've seen tech
> notes about a bug in system 7 that makes this sort of code run slowly. Is
> this true? Are there work-arounds available.
>
The only "problem" with System 7 and color has to do with calling
SetCtlValue() on things like scrollbars to often.
Your problem is more likely the calls to DrawChar(). Try doing some
buffering and calling DrawString() or DrawText() instead, that will speed
things up. Also look for multiple calls to setting/resetting colors, text
mode, etc. The things a good profiler would find.
Leonard
- ------------------------------------------------------------------------
Leonard Rosenthol Internet: leonardr@netcom.com
Director of Advanced Technology AppleLink: MACgician
Aladdin Systems, Inc. GEnie: MACgician
+++++++++++++++++++++++++++
>From trygve@apple.com (Trygve Isaacson)
Date: Thu, 10 Mar 1994 01:06:06 -0800
Organization: Apple Computer, Inc.
In article <mbayme-060394133729@bayme.bih.harvard.edu>,
mbayme@bih.harvard.edu (Michael J. Bayme, M.D.) wrote:
> Hi! I'm writing a color terminal emultor for my hospital's system - and
> it's slow. I use srcCopy and lots of DrawChars - it's slow. I've seen tech
> notes about a bug in system 7 that makes this sort of code run slowly. Is
> this true? Are there work-arounds available.
> Thanks, Michael Bayme
Fortunately, yes. Terminal emulators were among the first to hit this
problem because few other programs' performance relies on the speed of
drawing text on a colored background.
The solution is to use srcOr instead of srcCopy (srcOr is fast). But this
means you are responsible for filling in the background color before
drawing. So:
- First, paint the invalid area with the background color
- Then, draw the text with the foreground color using srcOr
Unfortunately, this two-phase drawing is visibly a bit uglier than srcCopy,
but if you spend a little extra effort to do it offscreen, it will look
even better than before.
While I'm yacking, here are a couple of other speed tips:
1) Don't draw character by character: instead, draw an entire run of text
at a time, where a run is defined as all adjacent characters that can be
drawn with the same pen/color/style/whatever. (OK, this is obvious;
otherwise your drawing would already be intolerably slow.)
2) Optimize out whitespace: move the pen instead of drawing blanks. Of
course, this assumes you can calculate the character width ahead of time,
which assumes you're using a monospaced font. Note that boldface throws a
wrench in things unless your font's bold maintains the same character width
as plain, as does our Noiro font shipped with the SNA%ps emulators.
3) Optimize out areas (rows/cols) that don't need to be drawn, such as
areas outside the window update region, and areas outside the modified
data. In other words, don't let clipping do all your work for you. It's
faster to calculate what doesn't need to be drawn than to actually draw
text that will be clipped.
4) When you get new data to draw, don't just invalidate and sit there
waiting for an update event; draw immediately.
Hmmm, that's it off the top of my head.... Good luck...
Trygve Isaacson
SNA%ps engineer
Apple Computer, Inc.
+++++++++++++++++++++++++++
>From msouth@BIX.com (msouth on BIX)
Date: 12 Mar 94 04:28:12 GMT
Organization: Delphi Internet Services Corporation
More terminal-emulation tips of varying usefullness:
5) Don't scroll with every linefeed received. Instead, save up text
and scroll a certain number of times per second.
5) Get complicated. Most of the CPU time is probablly being
used to scroll text up one line with every linefeed received.
Instead, save up incoming text (by drawing to offscreen bitmap?),
and scroll in three or four lines at a time. You can't see more
than 20 frames or so a second, so 60 lines a secord (for instance)
would be wasting a lot of time. Even 5 or 10 refreshes a second
can be bearable.
Mike South
---------------------------
>From warwick_j@cubldr.colorado.edu
Subject: DrawString + Ellipsis character ?
Date: Thu, 10 Mar 1994 10:35:24 GMT
Organization: University of Colorado, Boulder
What is the best way to draw a Str255 into a Rect, abbreviating the
string if it doesn't fit by putting an ellipsis at the end?
The Finder does this for its By Name views, for example, when one of the
fields doesn't fit into the space provided. I seem to remember seeing a
routine to do this documented somewhere.
Obviously it would be simple to write, but I'd hate to reinvent the
wheel...
Nick.
+++++++++++++++++++++++++++
>From Lars.Farm@nts.mh.se (Lars Farm)
Date: Thu, 10 Mar 1994 14:34:24 +0100
Organization: Mid Sweden University
In article <1994Mar10.033524.1@cubldr.colorado.edu>,
warwick_j@cubldr.colorado.edu wrote:
> What is the best way to draw a Str255 into a Rect, abbreviating the
> string if it doesn't fit by putting an ellipsis at the end?
Use the Script Manager routine TruncString() or TruncText().
See: TextUtils.h or Script.h
--
Lars.Farm@nts.mh.se
+++++++++++++++++++++++++++
>From harveyj@dunx1.ocs.drexel.edu. (John Harvey)
Date: Thu, 10 Mar 1994 16:36:04 GMT
Organization: Drexel University
In article <1994Mar10.033524.1@cubldr.colorado.edu>
warwick_j@cubldr.colorado.edu writes:
> What is the best way to draw a Str255 into a Rect, abbreviating the
> string if it doesn't fit by putting an ellipsis at the end?
Use either of these two traps:
FUNCTION TruncText (width: Integer; textPtr: Ptr;
VAR length: Integer;
truncWhere: TruncCode): Integer;
or
FUNCTION TruncString (width: Integer; VAR theString: Str255;
truncWhere: TruncCode): Integer;
They both will return a hunk of text which will fit in the width
specified and has the correct truncation symbol(internationally
speaking). IM-Text 5-71 to 5-72 has the details.
John Harvey
+++++++++++++++++++++++++++
>From mgr@aggroup.aggroup.com (Mike Russell)
Date: Thu, 10 Mar 1994 12:44:02 -0800
Organization: the ag group, inc.
In article <1994Mar10.033524.1@cubldr.colorado.edu>,
warwick_j@cubldr.colorado.edu wrote:
> What is the best way to draw a Str255 into a Rect, abbreviating the
> string if it doesn't fit by putting an ellipsis at the end?
Here's some code that tries to use condensed text, then truncates the
center of the string.
- --
/*
* shoehorn - shrink a name to the specified width by first setting
condensed text
* face, then deleting letters from the middle. Returns the value
* of StringWidth(). Returns the final width.
*
* Face is not altered if it is already nonzero.
*/
int
shoehorn(StringPtr name, int *face, int w)
{
int extra = (*face & italic)?CharWidth(' '):0;
int ww;
int elipsis = 0;
Ptr p;
while(name[0] > 1 && (ww=StringWidth(name) + extra) > w) {
if(!name[0] || !w) return ww;
if(!(*face & condense)) {
TextFace(*face |= condense);
} else {
if(!elipsis)
name[elipsis = name[0]/2] = 'I';
p = (Ptr)name + elipsis + 1;
if(elipsis > name[0]/2) {
p -= 2;
elipsis--;
}
BlockMove(p+1, p, name[0] - (p - (Ptr)name));
name[0]--;
}
}
return ww;
}
+++++++++++++++++++++++++++
>From harveyj@dunx1.ocs.drexel.edu. (harveyj)
Date: Mon, 14 Mar 1994 16:08:54 GMT
Organization: Drexel University, Office Of Computing Services
In article <B.Kobben-140394142336@karto516.frw.ruu.nl>
B.Kobben@frw.ruu.nl (Barend Kobben) writes:
> I have not got IM-Text (yet), but Trunctext and Truncstring aren't in Think
> Reference either. Could this be correct? Anyway, do these functions work if
> I want to offer sys 6 compatibility?
I don't own a paper copy of IM-Text myself, but I'm getting by with
copies on CD's that are lying around my place of work.
Anyway, TruncText and TruncString are not available prior to 7.0
script manager. If you want to do the right thing internationally on
systems earlier than 7.0 you need to dig the ellipsis character out of
the 'itl4' resource's untoken table yourself and then measure your
text to figure out where to put the ellipsis character. IM-Text has
some example code for finding the token table and retrieving the
desired character. Here it is (I know it is in Pascal, blame IM-Text
not me):
PROCEDURE MyMapTokenToString(theScript: ScriptCode; theToken: Integer;
VAR theString: Str255);
VAR
itlHandle: Handle;
untokenOffset: LongInt;
untokenLength: LongInt;
untokenPtr: UntokenTablePtr;
untokenStringPtr: StringPtr;
BEGIN
GetIntlResourceTable(theScript, smUnTokenTable, itlHandle,
untokenOffset, untokenLength);
IF itlHandle = NIL THEN {handle errors, return null string}
theString := ''
ELSE BEGIN {make untokenPtr point to the }
{ beginning of the untoken table}
untokenPtr := UntokenTablePtr(LongInt(itlHandle^) +
untokenOffset);
IF theToken > untokenPtr^.lastToken THEN {this token is
}
{ not in table-- }
theString := '' { return null string}
ELSE BEGIN {index[theToken] is the offset }
{ of the desired string from the }
{ beginning of the untoken table}
untokenStringPtr := StringPtr(LongInt(untokenPtr)
+untokenPtr^.index[theToken]);
theString := untokenStringPtr^;
END;
END;
I'll leave the measuring code and inserting the character to the reader
(there was another posting which provided code to do that, I think).
Of course, if you don't mind the ellipsis character turning into a
hiragana character on a Japanese system ( and other things on other
non-roman systems), the easiest thing to do is just hardwire the
ellipsis character.
If you worry much about text on the Mac then IM-Text is a pretty
important investment. Stuff that was scattered everywhere is finally
together in one book, and questions about when features are available
are easily answered.
Sorry, I didn't include a mention of 6.0 compatibility before.
John Harvey
+++++++++++++++++++++++++++
>From Lars.Farm@nts.mh.se (Lars Farm)
Date: Tue, 15 Mar 1994 10:43:13 +0100
Organization: Mid Sweden University
In article <1994Mar14.160854.3349@netnews.noc.drexel.edu>,
harveyj@dunx1.ocs.drexel.edu. (harveyj) wrote:
> Anyway, TruncText and TruncString are not available prior to 7.0
> script manager.
They were introduced in 6.0.3 or 6.0.4 I think, with Upr/LwrText and others
in the script manager.
Lars
--
Lars.Farm@nts.mh.se
+++++++++++++++++++++++++++
>From harveyj@dunx1.ocs.drexel.edu. (harveyj)
Date: Tue, 15 Mar 1994 13:11:49 GMT
Organization: Drexel University, Office Of Computing Services
In article <Lars.Farm-150394104313@sleipner.nts.mh.se>
Lars.Farm@nts.mh.se (Lars Farm) writes:
> They were introduced in 6.0.3 or 6.0.4 I think, with Upr/LwrText and others
> in the script manager.
I sound like a parrot with this IM-Text stuff, but table 6-1 on page
6-6 of IM-Text says that TruncText and TruncString were introduced with
version 7.0 Script Manager. Version 7.0 Script Manager was first
released with system 7.0 (table 6-2 page 6-9 of IM-Text).
Like Al Smith said, "Let's look at the record." Of course, I've
apparently lost my mind to quote somebody without a reference. But, I
think I saw the quote in _Mad Magazine_, April 1964. OK?
John Harvey
---------------------------
>From klug@genesis.nred.ma.us (Mark Pirri)
Subject: Finder comments on non-Desktop DB volumes?
Date: Fri, 11 Mar 1994 05:14:07 GMT
Organization: Genesis Public Access Unix +1 508 664 0149
Is it possible to read the Finder comments for files on a <2MB volume
(i.e. no Desktop database) in System 7. I know that they're stored in the
old-style Desktop file (resource type 'FCMT' or something like that), but
since the Finder always keeps that open, how can I access them?
Any assistance would be greatly appreciated.
Thanks in advance
-mark p
--
- ------------------------------\
Mark N. Pirri \ THIS SPACE FOR RENT
internet: klug@genesis.nred.ma.us \ no corny .sig's, please!
AOL: TheVortex [@aol.com] \
+++++++++++++++++++++++++++
>From kd@summit.novell.com (Delbarre K.)
Date: 11 Mar 1994 20:18:40 -0500
Organization: Novell, Summit
In article <CMHIJK.HEw@genesis.nred.ma.us> klug@genesis.nred.ma.us (Mark Pirri) writes:
>Is it possible to read the Finder comments for files on a <2MB volume
>(i.e. no Desktop database) in System 7. I know that they're stored in the
>old-style Desktop file (resource type 'FCMT' or something like that), but
>since the Finder always keeps that open, how can I access them? [ ... ]
You can open the Desktop resource file read-only using
FSpOpenResFile(spec, fsRdPerm) or some variant thereof.
TN212 says to avoid opening a resource file read-only,
because it could lead to a corrupted resource map.
If there is a safer alternative I'd love to hear about it.
My utility GetInfo exists primarily to allow you to save
and restore all of your comments from a System 7 Desktop
Database, but also has the capability of extracting the
comments from an old-style Desktop resource file. It
uses FSpOpenResFile(spec, fsRdPerm) to open the resource
file for the reason you mention.
--
Kelvin Delbarre, Omicron Software Systems, Inc.
contracted to Novell's UNIX System Laboratories, Summit, NJ
kd@summit.novell.com
+++++++++++++++++++++++++++
>From ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University)
Date: 14 Mar 94 18:05:57 +1300
Organization: University of Waikato, Hamilton, New Zealand
In article <CMHIJK.HEw@genesis.nred.ma.us>, klug@genesis.nred.ma.us (Mark Pirri) writes:
> Is it possible to read the Finder comments for files on a <2MB volume
> (i.e. no Desktop database) in System 7. I know that they're stored in the
> old-style Desktop file (resource type 'FCMT' or something like that), but
> since the Finder always keeps that open, how can I access them?
Here's an idea I came up with. Unfortunately, it'll only work with Finder 7.1.3
(which makes proper use of the AppleEvent Manager):
* Install a system handler for a custom AppleEvent.
* Send this event to the Finder, so it executes your custom event handler
in the Finder's process context.
* Your custom handler now has full access to all the resource files the Finder
has open, including the desktop database on <2MB volumes.
Now, can anyone figure out how to make this work with pre-7.1.x Finders...?
Lawrence
(had a lot of fun with special kernel ASTs under VAX/VMS)
+++++++++++++++++++++++++++
>From leonardr@netcom.com (Leonard Rosenthol)
Date: Tue, 15 Mar 1994 20:03:10 GMT
Organization: Aladdin Systems, Inc.
In article <1994Mar14.180557.26363@waikato.ac.nz>, ldo@waikato.ac.nz
(Lawrence D'Oliveiro, Waikato University) wrote:
> Here's an idea I came up with.
> Unfortunately, it'll only work with Finder 7.1.3
> (which makes proper use of the AppleEvent Manager):
>
> * Install a system handler for a custom AppleEvent.
> * Send this event to the Finder, so it executes your custom event handler
> in the Finder's process context.
> * Your custom handler now has full access to all the resource files the Finder
> has open, including the desktop database on <2MB volumes.
>
> Now, can anyone figure out how to make this work with pre-7.1.x Finders...?
>
Actually it will work JUST FINE under ANY version of System 7, since
even older versions of the Finder will end up "forwarding" on the event to
the system handlers.
In fact, this is how OSA Menu works - it sends an event to the current
process that should end up getting ignored and processed by my system
handler.
Leonard
- ------------------------------------------------------------------------
Leonard Rosenthol Internet: leonardr@netcom.com
Director of Advanced Technology AppleLink: MACgician
Aladdin Systems, Inc. GEnie: MACgician
---------------------------
>From ssiegler@hns.com (Stuart Sieger)
Subject: Finding System Folder (Again)
Date: Mon, 28 Feb 1994 18:54:49 GMT
Organization: Hughes Network Systems Inc.
OK, Im hopeless.
I am trying to "find" the system folder so that I can put my
preferences there...
How does one go about that? I read that FindFolder works for sys7
only (and I still need to support sys6). Can someone give me
a code frag (or point me in the right direction) to locate the
system folder (or at least locate the path-string that leads
to the folder (ie, disk:System Folder:Preferences).
Any other suggestions (other than RTFM (I already tried that))
would be helpful.
Stuart Siegler
"Just because you're paranoid doesn't mean they aren't out to get you"
+++++++++++++++++++++++++++
>From alana@cs.uoregon.edu (Alan Akins)
Date: 3 Mar 1994 09:19:45 -0800
Organization: The uncharted backwaters of the unfashionable end of the Western Spiral arm of the Galaxy.
In article <1994Feb28.185449.22632@hns.com>,
Stuart Sieger <ssiegler@hns.com> wrote:
>
> I am trying to "find" the system folder so that I can put my
> preferences there...
>
> How does one go about that? I read that FindFolder works for sys7
> only (and I still need to support sys6). Can someone give me
> a code frag (or point me in the right direction) to locate the
> system folder (or at least locate the path-string that leads
> to the folder (ie, disk:System Folder:Preferences).
OK. Using FindFolder with System 7 is all I can help you with. I know
that glue code is supplied in THINK C for System 6 as well, but I've
never tried anything I've written with pre Sys7 systems.
FindFolder is doc'd in IM: Mac TB Essentials 7-54 thru 7-56 and is defined:
FUNCTION FindFolder( vRefNum: Integer; folderType: OSType;
createFolder: Boolean; VAR foundVRefNum: Integer;
VAR foundDirID: LongInt): OSErr;
The System Folder has constant type kSystemFolderType. For my
example, we also depend on the system constants kOnSystemDisk and
kCreateFolder.
So, one would use it like this (in C):
long
FindSysFolder( void )
{
long dirID;
short vRefNum;
OSErr err;
err = FindFolder( kOnSystemDisk, kSystemFolderType, kCreateFolder,
&vRefNum, &dirID );
if ( err == noErr )
return dirID;
else
/* Do some error recovery here */
;
}
This will look for the System Folder on the startup disk and if it is
not found, it will be created. Since it looks on the startup disk, it
should definitely be able to find it!
Hope this all helps!
--
* "Evan's been doing parallel | Alan Akins *
* processing for so long... | alana@cs.uoregon.edu *
* he's beside himself." | University of Oregon *
* - Me | Department of Computer Science *
+++++++++++++++++++++++++++
>From Steve Bryan <sbryan@maroon.tc.umn.edu>
Date: Fri, 4 Mar 1994 06:20:56 GMT
Organization: Sexton Software
In article <1994Feb28.185449.22632@hns.com> Stuart Sieger,
ssiegler@hns.com writes:
> only (and I still need to support sys6). Can someone give me
> a code frag (or point me in the right direction) to locate the
> system folder (or at least locate the path-string that leads
> to the folder (ie, disk:System Folder:Preferences).
Call SysEnvirons. This sets a variable of type SysEnvRec. One of its
fields is sysVRefNum which is a working directory refNum for the system
folder. If you need its 'real' vRefNum and dirID use sysVRefNum and a
call to PBGetWDInfo.
Steve Bryan InterNet: sbryan@maroon.tc.umn.edu
Sexton Software CompuServe: 76545,527
Minneapolis, MN Fax: (612) 929-1799
---------------------------
>From kurisuto@chopin.udel.edu (Sean J. Crist)
Subject: Free code: Sean's window manager
Date: 8 Mar 1994 20:07:11 -0500
Organization: University of Delaware
Following is the Pascal code I mentioned on an earlier post; since a few
people have expressed an interest, I'll go ahead and post it.
This is basically an extension to the Window Manager with two functions:
1) it supports floating palettes associated with specific windows, and 2)
it helps keep track of which window is which when your application allows
the user to open any number of windows (e.g. if you're writing a word
processor which allows any number of documents to be open at once, this
code helps to tell the document windows apart from each other without
maintaining a WindowPtr to each one).
Sorry that this is isn't binhexed or compressed. This code may be freely
incorporated into shareware programs, but I reserve all other rights.
Military use of this code is specifically prohibited.
unit SeansWindowManager;
{Copyright 1994 by Sean Crist (kurisuto@chopin.udel.edu). This code may be
freely incorporated into shareware}
{or freeware projects. All other rights reserved.}
{I am aware of no bugs in this code, but please send me reports of any
bugs you find.}
{ What this code is for: This is basically an extension to the
Window Manager 1) to support floating palettes, and}
{ 2) to obviate the need to keep WindowPtr's to each window. If you are
writing an application with a fixed number}
{of windows, you can just define your WindowPtr's as globals, but if your
application supports arbitrary}
{numbers of windows (e.g. a word processor which allows any number of
documents to be open at a time), it can be}
{a hassle to keep track of all of these WindowPtr's in a variable-length
array or whatever. The following code}
{makes it easy to manage large numbers of windows of assorted kinds. }
{ The basic strategy here is to put a handle in the RefCon of every
window opened by your application (not only}
{your 'document' windows but also your Clipboard window, your modeless
dialogs, etc). This handle contains}
{information uniquely identifying the window. You don't need to keep any
pointers to specific windows; when you}
{want a certain window, you just call one of the routines below, giving
information to identify the window.}
{The code below quickly looks through all the windows and gives you a
pointer to the window you want.}
{ Of course, you need not be greatly concerned with these handles;
just make the appropriate calls to the}
{routines below, and most of the grubby work will be done for you.}
{There's several changes you must make to your code, and to the code
below, for this all to work properly:}
{1. You must edit the list of wTypes below to reflect all the kinds of
windows your program supports.}
{2. You must edit the SetPrivateHilite routine below to reflect the
relation between palettes and regular}
{ windows in a way specific to your application. For example, if
you want your wToolsPalette to become}
{ visible when one of you wArtWindows is selected, you should code
this here.}
{3. Your program's initialization routine must set the
PrivateFrontWindow global (declared below) to some}
{ valid WindowPtr. It doesn't matter which window this is, as long
as it is a valid one. The code below}
{ will change the PrivateFrontWindow in response to your calls, but
it needs a window to start out with.}
{4. Every time you open a new window, you must call InitializeWindow on
it to record what kind of window it is.}
{ Just before you dispose of a window, you must call DisposeWData on
it first.}
{5. You must not call the Toolbox routine SelectWindow, since this will
mess up the hiliting of windows and }
{ visibility of palettes. Use the routine PrivateActivate (defined
below) instead.}
{6. In your event loop, you need to do a little extra work to support
floating palettes. We treat a window and }
{ its palettes as one 'layer'. When you get a mousedown in
PrivateFrontWindow, or in one of the palettes}
{ belonging to PrivateFrontWindow, then you should just call
BringToFront on that window.}
{ (Your event code thus needs to be smart about what kinds of
palettes belong to what kinds }
{ of windows.)}
{ If the mousedown is in some other window (i.e. neither
PrivateFrontWindow nor its palettes), then you should}
{ call PrivateActivate, which is much like SelectWindow except that
it does the extra work to support floating}
{ palettes and make sure everything gets hilited properly.}
interface
{Window types}
const
wMiscWindow = 1;
wMiscWindowWithPalette = 2;
wMiscPalette = 3;
{These window types are just to illustrate how this code works. In your
program, you would want to change these}
{constants to whatever kinds of windows your program supports. (The
application I'm working on has about 15}
{different kinds of windows and three kinds of palettes, for example.)
Each window type, including palettes, must}
{have a unique identifying number.}
const
BadWindow = 9999;
{For doing error checking. We send this to our own error handlers,
pretending it's a real Toolbox error code.}
var
PrivateFrontWindow: WindowPtr;
{This is the WindowPtr to the window that we _consider_ to be the front
window, ignoring whatever floating palettes}
{might be in front of it in the actual window list. Note: you must
initialize this to some valid WindowPtr when your}
{program initializes itself, or this code will crash.}
{We store the following record as a handle in the RefCon field of a
window. It contains all of our information that}
{we need to keep track of what kind of window this is. Most of the time,
you'll never need to manipulate the contents}
{of this record directly, since there's more convenient routines below to
do this work for you.}
type
WindowData = record
Class: Integer; {What kind of window or dialog? This is one of
the wType constants above.}
Owner: Integer;
Index: Integer;
DataHandle: Handle; {Handle to whatever other data you wish to store
for this window.}
AuxData: Integer; {To be used however you like.}
end;
WDataPtr = ^WindowData;
WDataHandle = ^WDataPtr;
{ Note on the fields 'Class', 'Owner', and 'Index': the Class is the
kind of window, e.g. a Clipboard window,}
{a search-and-replace modeless dialog, or whatever. This field contains
one of the wType constants defined above.}
{The owner and index tell which window of that kind we are talking
about. In the case where there's only one }
{instance of a kind of window (such as a Clipboard window), you can just
set Owner and Index to 0 when you call }
{InitializeWindow. When there's more than one instance of a particular
window type, give each window a different }
{Index to distinguish it.}
{ Under normal circumstances, you can just set Owner to 0 in all
cases. I include this field because my application }
{has script windows for different kinds of objects, so I need to know if
this is, say, the script window for}
{the 7th zone or the 7th room or whatever.}
{Call InitializeWindow when you are opening a new window. You are
responsible for creating the window with}
{GetNewCWindow or GetNewDialog or whatever; pass this handle in
WhichWindow. InitializeWindow allocates}
{a WDataHandle, installs it in the refCon of whichWindow, and sets up the
Class, Owner, and Index values.}
function InitializeWindow (whichWindow: WindowPtr; Class, Owner, Index:
Integer): Boolean;
{Dispose the WDataHandle associated with whichWindow. Note: You are
responsible for disposing whatever}
{data you have stored in DataHandle. The right order to dispose things
is: 1) dispose any data of your own}
{which you've stored in DataHandle 2) call DisposeWData 3) dispose of
the window or dialog itself with}
{the appropriate Toolbox call.}
procedure DisposeWData (whichWindow: WindowPtr);
{Store this handle in DataHandle.}
procedure SetWHandle (whichWindow: WindowPtr; TheHandle: Handle);
{Return the handle stored in DataHandle.}
function GetWHandle (whichWindow: WindowPtr): Handle;
{Given a window, return its WDataHandle}
function GetWData (whichWindow: WindowPtr): WDataHandle;
{What is the class of whichWindow? (You could accomplish this same thing
by calling GetWData and then}
{looking at MyWData^^.Class, but this routine saves work.) Returns -1 if
the WData is bad (i.e., you probably}
{didn't call InitializeWindow on this window.}
function GetWClass (whichWindow: WindowPtr): Integer;
{What is the index of whichWindow? (You could accomplish this same thing
by calling GetWData and then}
{looking at MyWData^^.Index, but this routine saves work.) Returns -1 if
the WData is bad (i.e., you probably}
{didn't call InitializeWindow on this window.}
function GetWIndex (whichWindow: WindowPtr): Integer;
{Search through all the windows and try to find the one which has the
specified class, owner, and index.}
function SearchWindow (Class, Owner, Index: Integer): WindowPtr;
{Same as SearchWindow, but for windows like the Clipboard which have only
one instance.}
function FindUniqueWindow (Class: Integer): WindowPtr;
{Try to bring to front the window with this class, owner, and index.
Returns TRUE if there is no such window,}
{i.e. the window can't be activated and must be created. This can make
your code succinct; when the user}
{does some action to open a particular window, your routine MyOpenWindow
can start out 'if CantActivate}
{(the window I need) then (do whatever to open it, including calling
InitializeWindow)'.}
function CantActivate (Class, Owner, Index: Integer): Boolean;
{You should use this instead of SelectWindow.}
procedure PrivateActivate (whichWindow: WindowPtr);
implementation
procedure doOSErr (ErrorCode: Integer);
begin
{Handle the error however you like. I usually post an alert.}
end;
{Error checking. Make sure the WDataHandle is a valid one by checking
its length. This is}
{mainly for debugging.}
function IsValidWindowHandle (TheWDataHandle: WDataHandle): Boolean;
var
HandleSize: LongInt;
begin
IsValidWindowHandle := TRUE;
HandleSize := GetHandleSize(Handle(TheWDataHandle));
if HandleSize <> SizeOf(WindowData) then
IsValidWindowHandle := FALSE;
end;
function GetWData (whichWindow: WindowPtr): WDataHandle;
var
thePeek: WindowPeek;
TheHandle: Handle;
begin
if WhichWindow = nil then
begin
doOSErr(BadWindow);
GetWData := nil;
end
else
begin
thePeek := WindowPeek(WhichWindow);
TheHandle := Handle(thePeek^.RefCon);
GetWData := WDataHandle(TheHandle);
end;
end;
function GetWClass (whichWindow: WindowPtr): Integer;
var
WData: WDataHandle;
begin
WData := GetWData(whichWindow);
if IsValidWindowHandle(WData) then
GetWClass := WData^^.Class
else
GetWClass := -1;
end;
function GetWIndex (whichWindow: WindowPtr): Integer;
var
WData: WDataHandle;
begin
WData := GetWData(whichWindow);
if IsValidWindowHandle(WData) then
GetWIndex := WData^^.Index
else
GetWIndex := -1;
end;
function GetWHandle (whichWindow: WindowPtr): Handle;
var
WData: WDataHandle;
begin
WData := GetWData(whichWindow);
if IsValidWindowHandle(WData) then
GetWHandle := WData^^.DataHandle
else
begin
GetWHandle := nil;
doOSErr(BadWindow);
end;
end;
procedure SetWHandle (whichWindow: WindowPtr; TheHandle: Handle);
var
WData: WDataHandle;
begin
WData := GetWData(whichWindow);
if IsValidWindowHandle(WData) then
WData^^.DataHandle := TheHandle
else
doOSErr(BadWindow);
end;
function InitializeWindow (whichWindow: WindowPtr; Class, Owner, Index:
Integer): Boolean;
var
thePeek: WindowPeek;
WData: WDataHandle;
OkSoFar: Boolean;
Result: Integer;
begin
OkSoFar := true;
thePeek := WindowPeek(WhichWIndow);
WData := WDataHandle(NewHandle(SizeOf(WindowData)));
Result := MemError;
if Result <> 0 then
begin
OkSoFar := False;
doOSErr(MemError);
end;
if OkSoFar then
begin
thePeek^.RefCon := LongInt(WData);
WData^^.Class := Class;
WData^^.Owner := Owner;
WData^^.Index := Index;
end;
InitializeWindow := OkSoFar;
end;
procedure DisposeWData (whichWindow: WindowPtr);
var
WData: WDataHandle;
begin
WData := GetWData(whichWindow);
if IsValidWindowHandle(WData) then
DisposHandle(Handle(WData))
else
doOSErr(BadWindow);
end;
{I hope this is still a kosher way to find out which window is really in
the front! If this is no longer}
{kosher, then I'd just make an invisible window which is always frontmost
(a la BringToFront) and}
{use it as my starting point for the search through the linked list.}
function findFrontWindow: WindowPtr;
const
WindowList = $9D6;
type
PtrPtr = ^Ptr;
var
WindowListPtr: PtrPtr;
begin
WindowListPtr := Pointer(WindowList);
findFrontWindow := WindowPtr(WindowListPtr^); {was: FrontWindow}
end;
function SearchWindow (Class, Owner, Index: Integer): WindowPtr;
var
done: boolean;
ThisWindow, FoundWindow: WindowPtr;
WData: WDataHandle;
ThisWPeek: WindowPeek;
begin
done := false;
FoundWindow := nil;
ThisWindow := FindFrontWindow;
if ThisWindow <> nil then
while not done do
begin
WData := GetWData(ThisWindow);
if IsValidWindowHandle(WData) then
if WData^^.Class = Class then
if WData^^.Owner = Owner then
if WData^^.Index = Index then
begin
FoundWindow := ThisWindow;
Done := true;
end;
if not Done then
begin
ThisWPeek := WindowPeek(ThisWindow);
ThisWPeek := ThisWPeek^.nextWindow;
ThisWindow := WindowPtr(ThisWPeek);
if ThisWindow = nil then
Done := true;
end;
end;
SearchWindow := FoundWindow;
end;
function CantActivate (Class, Owner, Index: Integer): Boolean;
var
ThisWindow: WindowPtr;
begin
CantActivate := TRUE; {Assume the window doesn't exist.}
ThisWindow := SearchWindow(Class, Owner, Index);
if ThisWindow <> nil then
begin
SelectWindow(ThisWindow);
CantActivate := FALSE; {The window exists, so we _can_ activate it.}
end;
end;
function FindUniqueWindow (Class: Integer): WindowPtr;
begin
FindUniqueWindow := SearchWindow(Class, 0, 0);
{By convention, all unique windows have 0 and 0 as their other arguments.}
end;
procedure AutoPositionPalettes (WhichWindow: WindowPtr);
begin
{If you want your palettes to be automatically positioned next to a
certain kind of window, put code here}
{to move the palettes to the right position.}
end;
{This internal routine is used to hilite or unhilite windows. Note that
there's more going on here than}
{just drawing the hiliting on the window. For our purposes, 'hilite'
means 'bring it to the front, hilite it,}
{and display its palettes as well'. 'Unhilite' means 'Turn off its
hiliting, and hide its palettes also.'}
procedure SetPrivateHilite (whichWindow: WindowPtr; Hilite: Boolean);
begin
if WhichWindow = nil then
doOSErr(BadWindow);
if Hilite then
begin
BringToFront(whichWindow);
ShowHide(whichWindow, TRUE);
end;
HiliteWindow(whichWindow, Hilite);
{If this window has a palette, bring it to the front as well.}
case GetWClass(whichWindow) of
{You should modify the case selectors here to handle whatever kinds of
windows with palettes your application supports.}
wMiscWindowWithPalette:
begin
if Hilite then
begin
AutoPositionPalettes(whichWindow);
BringToFront(FindUniqueWindow(wMiscPalette));
end;
ShowHide(FindUniqueWindow(wMiscPalette), Hilite);
end;
end;
end;
{Since we're using windows in a slightly unorthodox way, we can't rely on
the Activate and Deactivate events}
{to do our work for us. doSendPrivateActivateMessage is the routine to
handle our equivalent of an Activate}
{event for the PrivateFrontWindow. (Palettes can never be the
PrivateFrontWindow, by definition.)}
procedure doSendPrivateActivateMessage (whichWindow: WindowPtr);
external;
procedure privateActivate (whichWindow: WindowPtr);
begin
SetPrivateHilite(PrivateFrontWindow, FALSE);
PrivateFrontWindow := whichWindow;
SetPrivateHilite(PrivateFrontWindow, TRUE);
{Then send a message to update menus, etc.}
doSendPrivateActivateMessage(PrivateFrontWindow);
end;
end.
---------------------------
>From grantd@dcs.gla.ac.uk (Dair Grant)
Subject: How does the Finder handle events?
Date: Wed, 9 Mar 1994 16:46:06 GMT
Organization: Glasgow University Computing Science Dept.
How does the Finder handle the high level Apple Events listed in its
'fmnu' resources? I've sat in the event queue and watched the same events
arriving from other applications as expected, but the Finder doesn't
appear to send anything to itself for the same event (e.g., 'sdup').
I've also tried installing new handlers to override any original handlers,
but they're never actually called - in fact, they don't actually get to
override anything, as there don't seem to be any handlers installed which
they can override.
What mechanism does the Finder use for handling these AEs? How do things
like CopyDoubler intercept control? Any ideas?
-dair
+++++++++++++++++++++++++++
>From hubauer@telerama.lm.com (Bill Hubauer)
Date: 10 Mar 1994 08:24:35 -0500
Organization: Telerama Public Access Internet, Pittsburgh, PA
Dair Grant (grantd@dcs.gla.ac.uk) wrote:
:
: How does the Finder handle the high level Apple Events listed in its
: 'fmnu' resources? I've sat in the event queue and watched the same events
: arriving from other applications as expected, but the Finder doesn't
: appear to send anything to itself for the same event (e.g., 'sdup').
:
: I've also tried installing new handlers to override any original handlers,
: but they're never actually called - in fact, they don't actually get to
: override anything, as there don't seem to be any handlers installed which
: they can override.
:
: What mechanism does the Finder use for handling these AEs? How do things
: like CopyDoubler intercept control? Any ideas?
:
:
:
: -dair
The non-scriptable finder does not use the apple event manager at all.
It just uses highlevel events and parses them without the help of the
apple event manager. This is why you can't patch in.
--
- -------------------------------------------
Bill Hubauer Hubauer@TeleRama.pgh.pa.us
AOL: MacBilly CIS: 76114,3012
+++++++++++++++++++++++++++
>From gurgle@netcom.com (Pete Gontier)
Date: Thu, 10 Mar 1994 17:45:01 GMT
Organization: cellular
hubauer@telerama.lm.com (Bill Hubauer) writes:
>Dair Grant (grantd@dcs.gla.ac.uk) wrote:
>: How does the Finder handle the high level Apple Events listed in its
>: 'fmnu' resources? I've sat in the event queue and watched the same
>: events arriving from other applications as expected, but the Finder
>: doesn't appear to send anything to itself for the same event (e.g.,
>: 'sdup').
>:
>: I've also tried installing new handlers to override any original
>: handlers, but they're never actually called - in fact, they don't
>: actually get to override anything, as there don't seem to be any
>: handlers installed which they can override.
>:
>: What mechanism does the Finder use for handling these AEs? How do
>: things like CopyDoubler intercept control? Any ideas?
>The non-scriptable finder does not use the apple event manager at all.
>It just uses highlevel events and parses them without the help of the
>apple event manager. This is why you can't patch in.
However, note that half of his investigations, he says, have been
with the event queue, not with the AppleEvent Manager. It would be
interesting to hear whether he is watching event records as they come
back from WNE or if he is waiting for Finder to call some other trap to
clue him in that there might be a high level event or AppleEvent being
handled. If the former, it sounds like Finder does not even defer its
event processing until the next iteration of the event loop. This would
not be surprising if Finder used AppleEvents, because the AE Manager
routes events sent to self directly to the handler. But we know Finder
is not using the AE Manager, so it might be that it sends high level
events to itself and somehow waits for the event loop to process them.
Then again, it might not. More information is in order. Oh, MacsBug...
ATB A88F rA7^.w==34
...which puts a break on PostHighLevelEvent, which is probably what
Finder would be using instead of AESend. Although it does get called
when Finder wants to open a document into a running app ('odoc' --
probably it's just the AE manager calling PostHighLevelEvent rather than
Finder), it doesn't get called when one makes a Finder menu selection
or drags an icon from one folder to another. However, doing little
investigations like this one is the very essence of this sort of hack.
Be persistent, and good luck.
--
Pete Gontier, CTO, Integer Poet Software; gurgle@netcom.com
---------------------------
>From dubois@uakari.primate.wisc.edu (Paul DuBois)
Subject: How to determine color of progress bar?
Date: 9 Mar 1994 23:05:40 -0600
Organization: Castra Parvulorum
When the Finder does a copy, it shows a progress bar. How do
I tell what the background and foreground colors of the bar are?
--
Paul DuBois
dubois@primate.wisc.edu
+++++++++++++++++++++++++++
>From kenlong@netcom.com (Ken Long)
Date: Thu, 10 Mar 1994 08:47:42 GMT
Organization: NETCOM On-line Communication Services (408 241-9760 guest)
Do you want to tell what color they are, or make them be a certain color?
The gray is RGB 17476, and the lavender is R 52428, G 52428, B 65535.
Kinda hard to screen shot it while a dialog's cookin', huh.
The above numbers are from Joe Zobkiw's "Finder Prgress", which should
also jive with Scott Knaster's "erasing your hard disk" SMP demo.
-Ken-
+++++++++++++++++++++++++++
>From kenlong@netcom.com (Ken Long)
Date: Thu, 10 Mar 1994 15:41:03 GMT
Organization: NETCOM On-line Communication Services (408 241-9760 guest)
That's "MPS" - not SMP. ("club" finger, late night, craniaplegic, no
glasses, keyboard worn out, etc.)
Mac Programming Secrets C source - dig?
-Ken-
+++++++++++++++++++++++++++
>From rmcassid@uci.edu (Robert Cassidy)
Date: Thu, 10 Mar 1994 10:24:22 -0700
Organization: TLG Project
In article <kenlongCMFxrI.Ep1@netcom.com>, kenlong@netcom.com (Ken Long)
wrote:
> Do you want to tell what color they are, or make them be a certain color?
>
> The gray is RGB 17476, and the lavender is R 52428, G 52428, B 65535.
>
> Kinda hard to screen shot it while a dialog's cookin', huh.
>
> The above numbers are from Joe Zobkiw's "Finder Prgress", which should
> also jive with Scott Knaster's "erasing your hard disk" SMP demo.
>
> -Ken-
Does the progress bar vary it's colors according to the Color control panel
the way windows do? (I'd check, but I have a *%&$@# monochrome monitor)
I've only looked at windows and controls but these two have optional color
tables or system default color tables (based on Color control panel
settings) that contain the proper values. Look at Troy Gaul's Infinity
Windoid code. His code can show you what to do for black and white as well
as color - very helpful.
--
Robert Cassidy
TLG Project
UC Irvine
Let's hope 'Information SuperTollroad' isn't the catchphrase of the next
decade...
+++++++++++++++++++++++++++
>From mgr@aggroup.aggroup.com (Mike Russell)
Date: Thu, 10 Mar 1994 12:40:57 -0800
Organization: the ag group, inc.
In article <2lm9r4INNj2v@uakari.primate.wisc.edu>,
dubois@uakari.primate.wisc.edu (Paul DuBois) wrote:
> When the Finder does a copy, it shows a progress bar. How do
> I tell what the background and foreground colors of the bar are?
I use shades of the user's select color, as someone suggested long
ago in this news group. That way you use a color that the user chose
and presumably likes.
+++++++++++++++++++++++++++
>From kenlong@netcom.com (Ken Long)
Date: Fri, 11 Mar 1994 01:25:27 GMT
Organization: NETCOM On-line Communication Services (408 241-9760 guest)
So how do you get the colors the user set with the Colors Control Panel?
Greg's buttons taps those, too.
I wasn't aware the progress colors change along with it. I'll have to
see that for myself. (Oh goody! Something else to do on my Mac!)
-Ken-
+++++++++++++++++++++++++++
>From troy@i-link.com (Troy Gaul)
Date: 11 Mar 1994 00:35:51 -0600
Organization: I-Link, Ltd., Des Moines, IA, USA - 515/255-2754
In article <kenlongCMH7yH.n0o@netcom.com>, Ken Long <kenlong@netcom.com> wrote:
>So how do you get the colors the user set with the Colors Control Panel?
>Greg's buttons taps those, too.
If you get the Infinity Windoid WDEF and look in the Windoid Util file,
there's a routine that gets a color from the window color table and sets
it as the fore (or back) color. For example, do a:
WctbForeColor(nil, wTingeLight);
[The nil is the window parameter, you could pass in the WindowPtr, but
if you use nil, it'll just use the default color table from the System.]
With the standard window colors, this maps to the steel blue that we all
know and love. With another tinge color, it maps to the appropriate
shade of that tinge.
>I wasn't aware the progress colors change along with it. I'll have to
>see that for myself. (Oh goody! Something else to do on my Mac!)
They don't. I've always thought this was a little odd. Actually, I've
tried doing a progress bar that uses the tinge color, but it doesn't
always look great (some of those tinge colors don't work well in that
large of an area).
_troy
--
//////// ////// Troy Gaul t-gaul@i-link.com //
// // I-Link, Ltd. //
// // // "Iungo ergo sum." (I-Link, therefore I am.) //
// ////// __________________________________________________________ //
+++++++++++++++++++++++++++
>From kenlong@netcom.com (Ken Long)
Date: Fri, 11 Mar 1994 09:06:30 GMT
Organization: NETCOM On-line Communication Services (408 241-9760 guest)
Thanks for that info, Troy. I'll have to get that WDEF out and
thoroughly read it, and read up on it!
-Ken-
"I love it when a plan comes together."
George Peppard as "Hannibal Smith"
+++++++++++++++++++++++++++
>From jwbaxter@olympus.net (John W. Baxter)
Date: Fri, 11 Mar 1994 12:58:24 -0800
Organization: Internet for the Olympic Peninsula
In article <mgr-100394124057@mike.aggroup.com>, mgr@aggroup.aggroup.com
(Mike Russell) wrote:
> I use shades of the user's select color, as someone suggested long
> ago in this news group. That way you use a color that the user chose
> and presumably likes.
As a user, I really wish you wouldn't (although for progress bars it's not
so bad). AppleScript Script Editor has "forced" me to use a neutral grey
for my highlight color, because it wants to use a shade of my highlight for
the frame of its script editing window (monitor in 16-color mode). With a
highly visible highlight color, the result is bizarre.
--
John Baxter Port Ludlow, WA, USA [West shore, Puget Sound]
jwbaxter@pt.olympus.net
+++++++++++++++++++++++++++
>From kenh@world.std.com (Ken Hancock)
Date: Sat, 12 Mar 1994 01:11:19 GMT
Organization: Isle Systems - Nashua, NH
In article <2lp3g7$l1p@ilink1.i-link.com>, Troy Gaul <troy@i-link.com> wrote:
>In article <kenlongCMH7yH.n0o@netcom.com>, Ken Long <kenlong@netcom.com> wrote:
>>I wasn't aware the progress colors change along with it. I'll have to
>>see that for myself. (Oh goody! Something else to do on my Mac!)
>
>They don't. I've always thought this was a little odd. Actually, I've
>tried doing a progress bar that uses the tinge color, but it doesn't
>always look great (some of those tinge colors don't work well in that
>large of an area).
This is one of the things which makes me think that the window color
control panel was a (good) hack by one of the engineeers who couldn't
stand the "standard" purple. Personally, I've always done my
progress bars using wTingeLight as Apple should have, IMHO.
(It loes look silly having everything else in the window gold or green
but still have that $#*& progress bar be purple)
Ken
--
Ken Hancock | INTERNET: kenh@vgi.com
Isle Systems | Compuserve: >INTERNET: kenh@vgi.com
Macintosh Consulting | AOL: KHancock
| Disclaimer: My opinions are mine,
+++++++++++++++++++++++++++
>From markhanrek@aol.com (MarkHanrek)
Date: 12 Mar 1994 04:54:01 -0500
Organization: America Online, Inc. (1-800-827-6364)
Do a cmd-shift-3 to take a snapshot of the screen while the progress dialog is
up, then use the eyedropper tool of any color graphics editing / paint program
to determine the RGB value or the indexed color value.
Mark Hanrek
+++++++++++++++++++++++++++
>From kenlong@netcom.com (Ken Long)
Date: Sat, 12 Mar 1994 19:14:30 GMT
Organization: NETCOM On-line Communication Services (408 241-9760 guest)
I don't know if it happens in every instance, but, usually, when there's
some operation going on and you try to do a screen shot, the command to
do the screen shot goes on the "waiting list" and is carried out after
the current operation is complete.
Sometimes you can sneak a screenshot in if the operation is operating in
a loop and checks for events (like the ones that look for keyDowns like
Command-. etc.).
But those colors are pretty easy to spot in a system color palette, in
ResEdit or a color paint program - especially after seeing them several
times a day, 7 days a week, for 2 (?) years.
-Ken-
+++++++++++++++++++++++++++
>From D.A.G.Gillies@bradford.ac.uk (David Gillies)
Date: Mon, 14 Mar 1994 17:57:47 GMT
Organization: Unseen University, Ankh-Morpork
In article <rmcassid-100394102422@rmcassidy.tlg.uci.edu> rmcassid@uci.edu (Robert Cassidy) writes:
>In article <kenlongCMFxrI.Ep1@netcom.com>, kenlong@netcom.com (Ken Long)
>wrote:
>
>> Do you want to tell what color they are, or make them be a certain color?
>>
>> The gray is RGB 17476, and the lavender is R 52428, G 52428, B 65535.
>>
>> Kinda hard to screen shot it while a dialog's cookin', huh.
>>
>> The above numbers are from Joe Zobkiw's "Finder Prgress", which should
>> also jive with Scott Knaster's "erasing your hard disk" SMP demo.
>>
>> -Ken-
>
>Does the progress bar vary it's colors according to the Color control panel
>the way windows do? (I'd check, but I have a *%&$@# monochrome monitor)
>I've only looked at windows and controls but these two have optional color
>tables or system default color tables (based on Color control panel
>settings) that contain the proper values. Look at Troy Gaul's Infinity
>Windoid code. His code can show you what to do for black and white as well
>as color - very helpful.
If it's any help, the lilac colour is no. 42 in the standard system palette.
I implement the progress bar by just having the system palette in my
application and calling PmForeColor(42). Maybe not very elegant, but hey, it
works.
______________________________________________________________________
David A. G. Gillies (D.A.G.Gillies@bradford.ac.uk)
(c) 1994 Wittgenstein and The Furniture Depository of The Living Dead
A little learning is a dangerous thing - but not half as dangerous as a
lot of ignorance.
- ---------------------REPLIES VIA EMAIL PLEASE-----------------------
_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
+++++++++++++++++++++++++++
>From walrathw@rferl.org (WalrathW)
Date: 14 Mar 94 15:31:56 -0500
Organization: RFE/RL Inc.
In article <2ls3fp$qta@search01.news.aol.com>
markhanrek@aol.com (MarkHanrek) writes:
> Do a cmd-shift-3 to take a snapshot of the screen while the progress dialog is
> up, then use the eyedropper tool of any color graphics editing / paint program
> to determine the RGB value or the indexed color value.
>
> Mark Hanrek
>
I should also point out a very useful set of FKEYs called Jon's FKEYs
which I use all the time. There is one which lets you get the color of
any pixel on the screen (in RGB, HSV, or CMY), and another which lets
you drag out a rect of marching ants and gives you the coordinates. I
use them all the time for determining what the cool colors other
developers are using in their hacks are. They're available at the usual
Mac archive sites.
________oOo________
Wayne Walrath
RFE/RL Inc.
walrathW@rferl.org
+++++++++++++++++++++++++++
>From zobkiw@datawatch.com (joe zobkiw)
Date: Tue, 15 Mar 1994 12:29:12 GMT
Organization: Datawatch Corporation
In article <1994Mar14.153157.371@dcvaxb.rferl.org>, walrathw@rferl.org
(WalrathW) wrote:
Forget it...use this routine...this will return the light and dark tinges
currently being used by the WDEF/CDEF in System 7 to draw things like
scroll bars and window borders, etc. You can then use these colors to draw
the foreground and background of your progress bar. This way, you will
always match what the user has selected in the Color control panel.
And NO you shouldn't release the resource. Try it and you'll see why :)
/*******************************************************************************
GetWindowTinges
Should have color quickdraw for this routine to be called
*******************************************************************************/
void GetWindowTinges(RGBColor *lightTinge, RGBColor *darkTinge)
{
CTabHandle windowCTable;
lightTinge->red = lightTinge->green = lightTinge->blue = 0xffff;
darkTinge->red = darkTinge->green = darkTinge->blue = 0x0000;
if ((windowCTable = (CTabHandle)GetResource('wctb', 0)) != nil) {
*lightTinge = (**windowCTable).ctTable[11].rgb;
*darkTinge = (**windowCTable).ctTable[12].rgb;
}
/* case for black and white window defs under system 7, both return black!
*/
if ((lightTinge->red == 0x0000) && (lightTinge->green == 0x0000) &&
(lightTinge->blue == 0x0000))
lightTinge->red = lightTinge->green = lightTinge->blue = 0xffff;
}
___________________________________________________________
_/_/_/_/ Joe Zobkiw ,,,
_/ Senior Software Engineer - -
_/ Datawatch Corporation L
_/_/_/_/ zobkiw@datawatch.com -
+++++++++++++++++++++++++++
>From KLUEV@jonathan.srcc.msu.su
Date: Wed, 16 Mar 1994 21:06:43 +0300
Organization: (none)
In article <zobkiw-150394072912@zobkiw.datawatch.com>
zobkiw@datawatch.com (joe zobkiw) writes:
>In article <1994Mar14.153157.371@dcvaxb.rferl.org>, walrathw@rferl.org
>(WalrathW) wrote:
>
>Forget it...use this routine...this will return the light and dark tinges
>currently being used by the WDEF/CDEF in System 7 to draw things like
>scroll bars and window borders, etc. You can then use these colors to draw
>the foreground and background of your progress bar. This way, you will
>always match what the user has selected in the Color control panel.
>
>And NO you shouldn't release the resource. Try it and you'll see why :)
>
... Code deleted ...
> if ((windowCTable = (CTabHandle)GetResource('wctb', 0)) != nil) {
> *lightTinge = (**windowCTable).ctTable[11].rgb;
> *darkTinge = (**windowCTable).ctTable[12].rgb;
...
It's better to use GetAuxWin procedure. This way you will take into
account custom 'wctb's.
Michael Kluev.
+++++++++++++++++++++++++++
>From rollin@newton.apple.com (Keith Rollin)
Date: Sun, 13 Mar 1994 01:32:55 GMT
Organization: Apple Computer, Inc.
In article <2ls3fp$qta@search01.news.aol.com>, markhanrek@aol.com
(MarkHanrek) wrote:
> Do a cmd-shift-3 to take a snapshot of the screen while the progress dialog is
> up, then use the eyedropper tool of any color graphics editing / paint program
> to determine the RGB value or the indexed color value.
A neat idea, but not the best way to go. The color specified by the program
drawing the progress bar (e.g., the Finder) is not necessarily the one that
appears on the screen. Instead, the RGB color specified is mapped to the
closest available color in the screen device's color table. To look at an
extreme example, if the screen is in B&W mode, a nice purple will get
mapped to black. Even on a 256 color device, the color specified will
almost always be different than that displayed.
When I was working on "Macintosh Programming Secrets", I wanted to get the
*exact* colors that the Finder was using. To do this, I set breakpoints on
a few of QuickDraw's calls (like PaintRect and FillCRect). I can't remember
exactly what call the Finder was using, but when I broke into the debugger,
I was able to either look at the color being passed into the call, or the
RGBForeColor in the current CGrafPort.
- --------------------------------------------------------------------------
Keith Rollin --- Phantom Programmer --- Apple Computer, Inc. --- Team
Newton
+++++++++++++++++++++++++++
>From melissa@i-link.com (Melissa Gaul)
Date: Wed, 16 Mar 1994 18:41:48 -0600
Organization: I-Link, Ltd.
In article <862D4F21C8@VADIK.srcc.msu.su>, KLUEV@jonathan.srcc.msu.su
wrote:
> In article <zobkiw-150394072912@zobkiw.datawatch.com>
> zobkiw@datawatch.com (joe zobkiw) writes:
> >In article <1994Mar14.153157.371@dcvaxb.rferl.org>, walrathw@rferl.org
> >(WalrathW) wrote:
> >
> >Forget it...use this routine...this will return the light and dark tinges
> >currently being used by the WDEF/CDEF in System 7 to draw things like
> >scroll bars and window borders, etc. You can then use these colors to draw
> >the foreground and background of your progress bar. This way, you will
> >always match what the user has selected in the Color control panel.
> >
> >And NO you shouldn't release the resource. Try it and you'll see why :)
> >
> ... Code deleted ...
> > if ((windowCTable = (CTabHandle)GetResource('wctb', 0)) != nil) {
> > *lightTinge = (**windowCTable).ctTable[11].rgb;
> > *darkTinge = (**windowCTable).ctTable[12].rgb;
> ...
>
> It's better to use GetAuxWin procedure. This way you will take into
> account custom 'wctb's.
If you do this, you should also be prepared in case the window's color
table (from GetAuxWin) isn't long enough to hold the tinge colors you're
looking for. Then, you could try GetAuxWin(nil) and try there, but this
might still not have enough, so you should have some built-in defaults.
(This all assumes you want to handle all cases. If you control the windows
in your application and know this isn't needed, you might be able to avoid
it.)
_troy
////////_//////___Troy Gaul_________________________t-gaul@i-link.com___//
// // I-Link, Ltd. //
// // // "Iungo ergo sum." (I-Link, therefore I am.) //
//____//////_________________________________________________________//
+++++++++++++++++++++++++++
>From giles@med.cornell.edu (Aaron Giles)
Date: Wed, 16 Mar 1994 22:12:52 -0500
Organization: Cornell University Medical College
In article <rollin-120394173255@rollin-keith.apple.com>,
rollin@newton.apple.com (Keith Rollin) wrote:
> In article <2ls3fp$qta@search01.news.aol.com>, markhanrek@aol.com
> (MarkHanrek) wrote:
>
>> Do a cmd-shift-3 to take a snapshot of the screen while the progress dialog is
>> up, then use the eyedropper tool of any color graphics editing / paint program
>> to determine the RGB value or the indexed color value.
>
> A neat idea, but not the best way to go. The color specified by the program
> drawing the progress bar (e.g., the Finder) is not necessarily the one that
> appears on the screen. Instead, the RGB color specified is mapped to the
> closest available color in the screen device's color table.
Of course, if you do this on a 24-bit color screen, you don't need to
worry. :-) If you want your progress bars to look like the Finder's, try:
static RGBColor gBarBackground = { 0xcccc, 0xcccc, 0xffff };
static RGBColor gBarForeground = { 0x6666, 0x6666, 0x6666 };
Assuming that "background" refers to the steel blue, and "foreground"
refers to the gray.
Aaron
--
Aaron Giles
Macintosh & Newton Developer
Cornell University Medical College
giles@med.cornell.edu
+++++++++++++++++++++++++++
>From troy@i-link.com (Troy Gaul)
Date: Thu, 17 Mar 1994 00:02:56 -0600
Organization: I-Link, Ltd.
>In article <melissa-160394184148@ts1-3.i-link.com>, melissa@i-link.com
>(Melissa Gaul) wrote:
Oops, that was supposed to be me, not my wife. :(
Just goes to show how a mechanism for having different preferences files
for two people who use the same machine can be important, I guess...
_troy
////////_//////___Troy Gaul_________________________t-gaul@i-link.com___//
// // I-Link, Ltd. //
// // // "Iungo ergo sum." (I-Link, therefore I am.) //
//____//////_________________________________________________________//
+++++++++++++++++++++++++++
>From arentz@batcave.knoware.nl (Stefan Arentz)
Date: Thu, 17 Mar 1994 17:15:57 GMT
Organization: Knoware
In article <rollin-120394173255@rollin-keith.apple.com>,
rollin@newton.apple.com (Keith Rollin) wrote:
> When I was working on "Macintosh Programming Secrets", I wanted to get the
> *exact* colors that the Finder was using. To do this, I set breakpoints on
> a few of QuickDraw's calls (like PaintRect and FillCRect). I can't remember
> exactly what call the Finder was using, but when I broke into the debugger,
> I was able to either look at the color being passed into the call, or the
> RGBForeColor in the current CGrafPort.
RGBColor CProgressIndicator::mBlack = { 0x0000, 0x0000, 0x0000 };
RGBColor CProgressIndicator::mWhite = { 0xFFFF, 0xFFFF, 0xFFFF };
RGBColor CProgressIndicator::mDarkGrey = { 0x4000, 0x4000, 0x4000 };
RGBColor CProgressIndicator::mSteelBlue = { 0xCCCC, 0xCCCC, 0xFFFF };
Black is black, White is white, SteelBlue is the background color of the
indicator, and DarkGray is the color of the moving bar...
Great Book Keith! ;-)
> ----------------------------------------------------------------------------
> Keith Rollin --- Phantom Programmer --- Apple Computer, Inc. --- Team Newton
Er, Team Newton? Does this mean we can expect a 'Newton Programming
Secrets'?
-- Stefan
- -----------------------------------------------------------------------
Stefan Arentz -- Lunatech Software Development -- arentz@knoware.nl
+++++++++++++++++++++++++++
>From mshields%peruvian.cs.utah.edu@cs.utah.edu (Michael S Shields)
Date: 17 Mar 94 16:25:05 MST
Organization: University of Utah Computer Science
Um,
I just did a little test and I found that the progress bar in a finder copy
doesn't depend on the window cor. I usually have my windws at the "Standard"
color, so I switched it to red and the progress bar was still in the dark grey/
purplish color combo. So, I think that putting up a progress bar in the window
colors might be unnerving to a user if you are trying to mimic the Finder.
Also, it's work you could eliminate to spend more time on other things.
Mike
mshields@peruvian.cs.utah.edu
mshields@dayna.com
---------------------------
>From peloy@ccxbbs.uunet.ve
Subject: How to draw inits icons?
Date: 2 Mar 1994 07:35:11 -0600
Organization: Caracas Computer Exchange BBS
To: comp-sys-mac-programmer@cs.utexas.edu
Hello there.
I've looking so far to find how to draw my INIT's icon on the bottom of the
screen at boot time. I haven't found anything in Inside Macintosh or in the
Technical Notes.
I would like to know how can I do this. I could borrow the code needed to draw
the icon from any INIT but I would like to understand how it works. When doing
"reverse engineering" on the code to draw INIT's icons, I've found some low
memory variables that are not documented.
It would be very fine if you can send me source code to do this or you can
explain me how to do my own code.
I don't have direct access to c.s.m.p. so please send your help to my
electronic address (peloy@ccxbbs.uunet.ve).
Thans a lot in advance,
Eloy A. Paris <peloy@ccxbbs.uunet.ve>
-> Alice4Mac 2.2.2E QWK Ser#127-1073
+++++++++++++++++++++++++++
>From kenlong@netcom.com (Ken Long)
Date: Wed, 2 Mar 1994 16:58:26 GMT
Organization: NETCOM On-line Communication Services (408 241-9760 guest)
There's a couple files you can get. Connect to:
ftp bigbird.csd.scarolina.edu
and in the pub/mac directory is Jim Walker's "ShowIcon7" - a C project
and info on doing that.
Then, in alt.sources.mac is a file I got off AOL that is a C project for
generic control panels and INITs which use "ShowINIT.c" to show it. I
tried the example CP in this file and it did, indeed, show its icon on
startup. The file is probably on sumex, as well.
-Ken-
---------------------------
>From dat91jre@ludat.lth.se (Regmyr Jonas)
Subject: How to tell a Mac from a Mac?
Date: 7 Mar 1994 08:49:33 GMT
Organization: Lund Institute of Technology, Sweden
Hi!
Is there a way to tell one Mac from anotherone or, is there a way
for a program to tell if it has been moved from one machine to
anotherone, possible the same type (from, say, one Classic to another)?
If so, how do I do this?
I've thought about some ways to achive this:
If there is a way to get the serial # of the machine the problem
is solved (probably won't work).
One could use the name of the boot volume but, what if the user
change it -> program will get confused (not so nice approach).
If there is a way to write to ROM there is a way to check the
appearance of some word, bit or whatever and by that know if
I've (the program) been here before (can one do this?).
For me, this problem is yet to be solved.
Please help me.
Thanx...
/Jonas...
--
Mail: Karl Jonas Regmyr Carl Hillsgatan 9 S-217 56 Malmoe Sweden
Phone: +46 (0)40 91 42 41 Email: dat91jre@ludat.lth.se
+++++++++++++++++++++++++++
>From d88-jwa@mumrik.nada.kth.se (Jon Wdtte)
Date: 7 Mar 1994 11:02:09 GMT
Organization: Royal Institute of Technology, Stockholm, Sweden
In <2lepqt$1g3@nic.lth.se> dat91jre@ludat.lth.se (Regmyr Jonas) writes:
>Is there a way to tell one Mac from anotherone or, is there a way
>for a program to tell if it has been moved from one machine to
>anotherone, possible the same type (from, say, one Classic to another)?
Yes; write your program to require an ADB dongle; thus if your
user moves the application but not the dongle (hardware key)
your app will notice it has been moved.
Copy protection in evil.
>If there is a way to get the serial # of the machine the problem
Nope.
>One could use the name of the boot volume but, what if the user
> change it -> program will get confused (not so nice approach).
Very bad; users switch between systems daily for things like
System 6 or Kanji or whatever.
>If there is a way to write to ROM there is a way to check the
> appearance of some word, bit or whatever and by that know if
> I've (the program) been here before (can one do this?).
ROM == Read-Only Memory == not-writable.
The simplest thing you can do is to check if your preferences
file is there in the preferences folder; if it's not, it's
probably a new installation (or the user installed a new system
or restored a backup, or switched systems or whatever)
--
-- Jon W{tte, h+@nada.kth.se, Mac Hacker Deluxe --
This article printed on 100% recycled electrons.
+++++++++++++++++++++++++++
>From Matt Slot <fprefect@engin.umich.edu>
Date: 7 Mar 1994 11:45:09 GMT
Organization: University of Michigan
Regmyr Jonas, dat91jre@ludat.lth.se writes:
>Is there a way to tell one Mac from another one or, is there a way
>for a program to tell if it has been moved from one machine to
>anotherone, possible the same type (from, say, one Classic to another)?
>If so, how do I do this?
- -----------
First a note: dont make self-modifying apps! Your app should not store
machine specific information within itself; if you save a preference
do it to a preferences file.
OK, off the podium. If you still need to identify a Mac from another,
use the Volume Creation date for VRefNum = -1. This is the long date
to the second of the initialization of that HD. For a 1 in 4 billion
chance of duplication, this works rather well. If the user *does*
reformat the boot disk, it will probably be a full reinstall and for
all intents a "new" machine.
Matt
+++++++++++++++++++++++++++
>From u9119523@sys.uea.ac.uk (Graham Cox)
Date: Mon, 7 Mar 1994 11:32:44 GMT
Organization: School of Information Systems, UEA, Norwich
In article <2lf1jh$rk2@news.kth.se>, d88-jwa@mumrik.nada.kth.se (Jon Wtte)
wrote:
> In <2lepqt$1g3@nic.lth.se> dat91jre@ludat.lth.se (Regmyr Jonas) writes:
>
> >Is there a way to tell one Mac from anotherone or, is there a way
> >for a program to tell if it has been moved from one machine to
> >anotherone, possible the same type (from, say, one Classic to another)?
Here's a simple way. Get the Date/Time of initialization of the startup
disk. As this is accurate to the second, the chance of two Macs having
their hard disks initialised at the same time is very small.
You can store this value in your app's preferences, and compare it with the
current disk at startup. If different, you can ask the user to enter a
validation code. If correct, you can then update the disk "ID" so the user
doesn't get bothered again, unless the program is copied to another
machine. If you add some kind of encryption to the stored values, the
likelihood of someone being able to hack the values is virtually
non-existent. I used this method on a commercial app and it works a treat.
It's also one of the few copy-protection methods thats absolutely
compatible with the system and unlikely to fail in future releases.
- ------------------------------------------------------------------------
Love & BSWK, Graham
-Everyone is entitled to their opinion, no matter how wrong they may be...
- ------------------------------------------------------------------------
+++++++++++++++++++++++++++
>From ajr3@quads.uchicago.edu (Alain Roy)
Date: Mon, 7 Mar 1994 15:00:36 GMT
Organization: University of Chicago
In article <u9119523-070394123244@graphics1.sys.uea.ac.uk> u9119523@sys.uea.ac.uk (Graham Cox) writes:
>
>Here's a simple way. Get the Date/Time of initialization of the startup
>disk. As this is accurate to the second, the chance of two Macs having
>their hard disks initialised at the same time is very small.
works unless you're like me: i have 2 hard drives. if every time i switched,
i had the copy protection of a program fire up, i'd be really upset.
-alain
+++++++++++++++++++++++++++
>From time@garnet.msen.com (Tim Endres)
Date: 7 Mar 1994 19:22:52 GMT
Organization: Msen, Inc. -- Ann Arbor, MI (account info: +1 313 998-4562)
Matt Slot (fprefect@engin.umich.edu) wrote:
: Regmyr Jonas, dat91jre@ludat.lth.se writes:
:
: >Is there a way to tell one Mac from another one or, is there a way
: >for a program to tell if it has been moved from one machine to
: >anotherone, possible the same type (from, say, one Classic to another)?
: >If so, how do I do this?
: -------------
: First a note: dont make self-modifying apps! Your app should not store
: machine specific information within itself; if you save a preference
: do it to a preferences file.
Unless you need a self-modifying app, such as TransIt.
: OK, off the podium. If you still need to identify a Mac from another,
: use the Volume Creation date for VRefNum = -1. This is the long date
: to the second of the initialization of that HD. For a 1 in 4 billion
Except that most times are in the range from 1984 to 1994, as
opposed to 1904 to 1994. Thus, closer to 478 Million. Still reasonable.
: chance of duplication, this works rather well. If the user *does*
: reformat the boot disk, it will probably be a full reinstall and for
: all intents a "new" machine.
Or, as pointed out, the user boots from more than one
volume. In this case, you need to keep a "list" of
drives, which may not be what you want.
+++++++++++++++++++++++++++
>From gregor@nrlfs1.nrl.navy.mil (joe gregor)
Date: Mon, 7 Mar 1994 19:45:14 GMT
Organization: NRL
In Article <2lf445$5qd@lastactionhero.rs.itd.umich.edu>, Matt Slot
<fprefect@engin.umich.edu> wrote:
>OK, off the podium. If you still need to identify a Mac from another,
>use the Volume Creation date for VRefNum = -1. This is the long date
>to the second of the initialization of that HD. For a 1 in 4 billion
>chance of duplication, this works rather well. If the user *does*
>reformat the boot disk, it will probably be a full reinstall and for
>all intents a "new" machine.
>
Never had to replace a hard disk before, huh.
-- Joe
+++++++++++++++++++++++++++
>From peirce@outpost.SF-Bay.org (Michael Peirce)
Date: Mon, 7 Mar 94 13:52:36 PST
Organization: Peirce Software, Inc.
In article <u9119523-070394123244@graphics1.sys.uea.ac.uk> (comp.sys.mac.programmer), u9119523@sys.uea.ac.uk (Graham Cox) writes:
> Here's a simple way. Get the Date/Time of initialization of the startup
> disk. As this is accurate to the second, the chance of two Macs having
> their hard disks initialised at the same time is very small.
>
> You can store this value in your app's preferences, and compare it with the
> current disk at startup. If different, you can ask the user to enter a
> validation code. If correct, you can then update the disk "ID" so the user
> doesn't get bothered again, unless the program is copied to another
> machine. If you add some kind of encryption to the stored values, the
> likelihood of someone being able to hack the values is virtually
> non-existent. I used this method on a commercial app and it works a treat.
> It's also one of the few copy-protection methods thats absolutely
> compatible with the system and unlikely to fail in future releases.
How do people feel about this technique. Are there any obvious drawbacks?
It does mean you need to "install" the software on each new system
disk, any objections to this?
-- Michael Peirce -- peirce@outpost.sf-bay.org
-- Peirce Software, Inc. -- 719 Hibiscus Place, Suite 301
-- -- San Jose, California USA 95117
-- Makers of: Smoothie & -- voice: +1.408.244.6554 fax: +1.408.244.6882
-- Peirce Print Tools -- AppleLink: peirce & America Online: AFC Peirce
+++++++++++++++++++++++++++
>From peter@ncrpda.curtin.edu.au (Peter N Lewis)
Date: 8 Mar 1994 13:04:08 +0800
Organization: NCRPDA, Curtin University
time@garnet.msen.com (Tim Endres) writes:
>: First a note: dont make self-modifying apps! Your app should not store
>: machine specific information within itself; if you save a preference
>: do it to a preferences file.
>Unless you need a self-modifying app, such as TransIt.
Besides, it's perfectly reasonable to modify yourself during instalation.
But it would definiitely be bad later on when the admin has writeprotected
the directory (and it's not much use on CDROMs either, etc).
>Or, as pointed out, the user boots from more than one
>volume. In this case, you need to keep a "list" of
>drives, which may not be what you want.
That's not really needed - if you boot from a seperate disk, then you'll
have a seperate prefs file, so you'll have to enter the serial number
once per system folder, thats not particularly unreasonable (and I hate
copy protection!).
The main draw back of this scheme is that it's a royal pain in the ass
for network mutli-user licenses. I think you can guess how happy I'd be
to buy a twenty user license and then have the fun of going around
typing serial numbers into every damn machine - and since this is such
a pain, I'll probably not recomend your software as the one to buy...
Peter.
--
Peter N Lewis <peter.lewis@info.curtin.edu.au> Ph: +61 9 368 2055
+++++++++++++++++++++++++++
>From ivanski@world.std.com (Ivan M CaveroBelaunde)
Date: Tue, 8 Mar 1994 16:30:43 GMT
Organization: The World Public Access UNIX, Brookline, MA
peirce@outpost.SF-Bay.org (Michael Peirce) writes:
>In article <u9119523-070394123244@graphics1.sys.uea.ac.uk> (comp.sys.mac.programmer), u9119523@sys.uea.ac.uk (Graham Cox) writes:
>> Here's a simple way. Get the Date/Time of initialization of the startup
>> disk. As this is accurate to the second, the chance of two Macs having
>> their hard disks initialised at the same time is very small.
>>
>> You can store this value in your app's preferences, and compare it with the
>> current disk at startup. If different, you can ask the user to enter a
>> validation code. If correct, you can then update the disk "ID" so the user
>> doesn't get bothered again, unless the program is copied to another
>> machine. If you add some kind of encryption to the stored values, the
>> likelihood of someone being able to hack the values is virtually
>> non-existent. I used this method on a commercial app and it works a treat.
>> It's also one of the few copy-protection methods thats absolutely
>> compatible with the system and unlikely to fail in future releases.
>How do people feel about this technique. Are there any obvious drawbacks?
>It does mean you need to "install" the software on each new system
>disk, any objections to this?
Actually, I really dislike the idea of having to install the software on
each new system, or being unable to switch to a different startup disk
(if say my startup volume died suddenly). I'd advocate a much different route
(which might be in use right now, since I've seen software behave this
way). Currently, a lot of software requires the user to do the first launch
on a writable volume in order to store registration information. As long
as it runs off of a read-only volume (ie a server) after that one registration
step, that doesn't bother me, and I don't think most users would be hassled
by this too much either. Consequently, I'd consider doing the following -
when prompting the user for registration information (which would be stored
inside the app), also look at the date/time of initialization of the
volume CONTAINING THE APP, and also look at the fileID of the app itself
(ie manually build a mini alias). Then store this information with the
registration information inside the app, and check against it at app
launch. This way, you can detect if the app file itself has been copied,
and reprompt for registration info if this is the case. The method is
flexible enough that if you wanted to allow some variants of copying
(ie doing a duplicate on the app file in the finder), you could check that
the app the reg info specifies is present and meets some basic checks
(as opposed to requiring that the app you are RUNNING is the app the reg
info points to). The other drawback is that this requires installation of
software on read-only servers by users with write permission - but this
requirement is present currently anyway.
Comments?
-Ivan
- -
Ivan Cavero Belaunde (ivanski@world.std.com)
Avid VideoShop Project Lead
Avid Technology, Inc.
+++++++++++++++++++++++++++
>From peirce@outpost.SF-Bay.org (Michael Peirce)
Date: Tue, 8 Mar 94 09:16:22 PST
Organization: Peirce Software, Inc.
In article <1994Mar7.150036.11171@midway.uchicago.edu> (comp.sys.mac.programmer), ajr3@quads.uchicago.edu (Alain Roy) writes:
> In article <u9119523-070394123244@graphics1.sys.uea.ac.uk> u9119523@sys.uea.ac.uk (Graham Cox) writes:
> >
> >Here's a simple way. Get the Date/Time of initialization of the startup
> >disk. As this is accurate to the second, the chance of two Macs having
> >their hard disks initialised at the same time is very small.
>
> works unless you're like me: i have 2 hard drives. if every time i switched,
> i had the copy protection of a program fire up, i'd be really upset.
But this would only happen the first time you started up on your second
disk. After that, its prefs file would contain the init time of *that*
disk.
-- Michael Peirce -- peirce@outpost.sf-bay.org
-- Peirce Software, Inc. -- 719 Hibiscus Place, Suite 301
-- -- San Jose, California USA 95117
-- Makers of: Smoothie & -- voice: +1.408.244.6554 fax: +1.408.244.6882
-- Peirce Print Tools -- AppleLink: peirce & America Online: AFC Peirce
+++++++++++++++++++++++++++
>From time@garnet.msen.com (Tim Endres)
Date: 8 Mar 1994 18:47:42 GMT
Organization: Msen, Inc. -- Ann Arbor, MI (account info: +1 313 998-4562)
I really like Ivan's idea of storing the time for the disk
that the *app* is on. This solves Peter's network installation
problems and it solves CD and server setups.
+++++++++++++++++++++++++++
>From mahboud@aggroup.com (Mahboud Zabetian)
Date: Tue, 08 Mar 1994 11:37:13 -0800
Organization: AG Group, Inc.
For macs with built-in Ethernet; Ethernet addresses are unique.
-mahboud
- -------------------------------------------------------------
Mahboud Zabetian
mahboud@aggroup.com
ag group, inc.
2540 camino diablo, suite 200
walnut creek, ca 94596
510-937-7900 voice
510-937-2479 fax
510-937-6704 ara
ftp.aggroup.com anonymous ftp
+++++++++++++++++++++++++++
>From Carl R. Osterwald <carl_osterwald@nrel.gov>
Date: Tue, 8 Mar 94 20:41:45 GMT
Organization: National Renewable Energy Laboratory
In article <mahboud-080394113713@mahboud.aggroup.com> Mahboud Zabetian,
mahboud@aggroup.com writes:
>For macs with built-in Ethernet; Ethernet addresses are unique.
True, but what about machines that use Ethernet cards? If the card is
changed for some reason, the nice app you spent good cash for no longer
runs.
+++++++++++++++++++++++++++
>From d88-jwa@mumrik.nada.kth.se (Jon Wdtte)
Date: 8 Mar 1994 21:16:28 GMT
Organization: Royal Institute of Technology, Stockholm, Sweden
In <CNjbKKKX.q1oh3b@outpost.SF-Bay.org> peirce@outpost.SF-Bay.org (Michael Peirce) writes:
>It does mean you need to "install" the software on each new system
>disk, any objections to this?
Not popular among large sites.
There is a way that an application can sense it's KeyServer
keyed and turn off its internal copy protection, though.
--
-- Jon W{tte, h+@nada.kth.se, Mac Hacker Deluxe --
I should have stayed at the bus station.
+++++++++++++++++++++++++++
>From DACRXL01.OURX124@tcp30.dx.deere.com (Juan Ingles)
Date: Wed, 9 Mar 1994 00:37:18 GMT
Organization: Proteus Ventures, Inc.
In article <A9A2311939027D1A@cro.nrel.gov>
Carl R. Osterwald <carl_osterwald@nrel.gov> writes:
> In article <mahboud-080394113713@mahboud.aggroup.com> Mahboud Zabetian,
> mahboud@aggroup.com writes:
> >For macs with built-in Ethernet; Ethernet addresses are unique.
>
> True, but what about machines that use Ethernet cards? If the card is
> changed for some reason, the nice app you spent good cash for no longer
> runs.
The ethernet address would still be the same. The address is assigned
to the machine and not to the card. The address is kept by the Mac TCP
software. (and can ussually be typed in by the user)
Addresses can and do change for other reasons, though. Administrators
can reassign addresses, the ethernet class could change, the machine
could be moved to a different network, etc.
Juan Ingles
<DACRXL01.OURX124@tcp30.dx.deere.com>
--
Proteus Ventures, Inc. - Computer Software Consulting and Development
1514 Oriole Ave * Waterloo, IA 50701 * (319) 232-0985
+++++++++++++++++++++++++++
>From peter@ncrpda.curtin.edu.au (Peter N Lewis)
Date: 9 Mar 1994 11:48:59 +0800
Organization: NCRPDA, Curtin University
ivanski@world.std.com (Ivan M CaveroBelaunde) writes:
>Actually, I really dislike the idea of having to install the software on
>each new system, or being unable to switch to a different startup disk
>(if say my startup volume died suddenly). I'd advocate a much different route
>(which might be in use right now, since I've seen software behave this
>way). Currently, a lot of software requires the user to do the first launch
>on a writable volume in order to store registration information. As long
The problem with both these solutions is they are a pain to setup in a
network environment, and since multiple copy licenses make up a large
chunk of the revenue, it really doesn't do to piss of these people with
anoying copy protection pains.
I don't mind software that asks you to register it with a serial number and
your name when you first install it, but if I have to do that for all
twenty copies that I bought, I wont buy them in the first place.
Piracy loses sales, but so does copy protection.
Peter.
--
Peter N Lewis <peter.lewis@info.curtin.edu.au> Ph: +61 9 368 2055
+++++++++++++++++++++++++++
>From ari@world.std.com (Ari I Halberstadt)
Date: Wed, 9 Mar 1994 07:31:34 GMT
Organization: The World Public Access UNIX, Brookline, MA
In article <2lf445$5qd@lastactionhero.rs.itd.umich.edu>,
Matt Slot <fprefect@engin.umich.edu> wrote:
>OK, off the podium. If you still need to identify a Mac from another,
>use the Volume Creation date for VRefNum = -1. This is the long date
>to the second of the initialization of that HD. For a 1 in 4 billion
>chance of duplication, this works rather well. If the user *does*
>reformat the boot disk, it will probably be a full reinstall and for
>all intents a "new" machine.
We can assume that all Macintosh hard drives have been formatted no
earlier than 1983 and no later than 1994 (assuming the user remembered
to set the clock before formatting). This gives a range of about
3.47x10^8 seconds, or 347 million. Most drives have probably been
formatted in only the last 4 years (there weren't even hard drives for
the mac until '85, I think), so it's probably more like 1.26x10^8
seconds. This is still a big number, but it's not nearly in the
billions.
--
Ari Halberstadt ari@world.std.com #include <std/disclaimer.h>
"These beetles were long considered to be very rare because very few
entomologists look for beetles in the mountains, in winter, at night,
during snow storms." -- Purves W. K., et al, "Life: The Science of
+++++++++++++++++++++++++++
>From dwalton1@bach.helios.nd.edu (david walton)
Date: 9 Mar 1994 08:21:54 GMT
Organization: University of Notre Dame, Notre Dame
In article <CMDGE6.5zt@deere.com> DACRXL01.OURX124@tcp30.dx.deere.com (Juan Ingles) writes:
>In article <A9A2311939027D1A@cro.nrel.gov>
>Carl R. Osterwald <carl_osterwald@nrel.gov> writes:
>
>> In article <mahboud-080394113713@mahboud.aggroup.com> Mahboud Zabetian,
>> mahboud@aggroup.com writes:
>> >For macs with built-in Ethernet; Ethernet addresses are unique.
>>
>> True, but what about machines that use Ethernet cards? If the card is
>> changed for some reason, the nice app you spent good cash for no longer
>> runs.
>
>The ethernet address would still be the same. The address is assigned
>to the machine and not to the card. The address is kept by the Mac TCP
>software. (and can ussually be typed in by the user)
*Ethernet* addresses are assigned to the physical hardware on the card
(which card may be moved around from machine to machine). *IP
addresses* (which I think is what you mean) are configurable by the
MacTCP Control Panel and can therefore be changed by any user
(although AdminTCP may be required if the network administrator was
smart enough to lock the settings). If some form of BOOTP is used,
then the administrator controls which interface gets which address,
but the user can always configure MacTCP to use a static address.
(Which address, btw, often ends up being one which was assigned to
another user--anyone who's dealt with the "this IP address is already
in use" message from MacTCP when some putz on your local network
steals an address will know exactly what I'm talking about).
Point is, you can't assume a fixed relationship between either
ethernet or IP addresses and a particular machine, except in the
limiting case where the ethernet hardware's built in. Hence, this
would not be a reliable copy-protection scheme in the general case.
Not that I _want_ copy-protection, mind you....
Now that I think about it, it's not trivial to get the Ethernet
address on built-in hardware if the machine doesn't have a transceiver
with an active link attached. (Is is possible to do this, BTW? I
don't see any way of doing it by making MacTCP calls, but is there a
lower-level driver call that could return this information?)
David
--
{ David Walton School: Dept. of History and Philosophy of Science }
{ Work: Office of University Computing }
{ Mail: David.Walton.10@nd.edu }
{ Any unquoted opinions expressed herein are...well...mine. Pity. }
+++++++++++++++++++++++++++
>From d88-jwa@mumrik.nada.kth.se (Jon Wdtte)
Date: 9 Mar 1994 15:07:28 GMT
Organization: Royal Institute of Technology, Stockholm, Sweden
In <CMDGE6.5zt@deere.com> DACRXL01.OURX124@tcp30.dx.deere.com (Juan Ingles) writes:
>> True, but what about machines that use Ethernet cards? If the card is
>> changed for some reason, the nice app you spent good cash for no longer
>> runs.
>The ethernet address would still be the same. The address is assigned
>to the machine and not to the card. The address is kept by the Mac TCP
>software. (and can ussually be typed in by the user)
PLEASE get your facts straigt at least.
Ethernet addresses are hardcoded in the Ethernet card ROM, and no
two cards EVER have the same address.
The IP address is what's maintained by MacTCP. Totally different
beast. Even if you don't install MacTCP, the ethernet address is
there in the ethernet card (even if you turn off AppleTalk!)
Ethernet breaks. Motherboard break. Users upgrade software. If
you've GOT to have copy protection, and don't mind breaking on
PowerBook Duos, use an ADB dongle; safe & efficient, upgradable,
and the money you save by not being pirated should pay for the
dongle price; if you subscribe to that theory. (I do for some
special niche products I make)
--
-- Jon W{tte, h+@nada.kth.se, Mac Hacker Deluxe --
What we need is a good GNU [...] licence manager implementation.
-- Raphael Manfredi
+++++++++++++++++++++++++++
>From DACRXL01.OURX124@tcp30.dx.deere.com (Juan Ingles)
Date: Wed, 9 Mar 1994 16:49:05 GMT
Organization: Proteus Ventures, Inc.
In article <2lk0v2$oq3@news.nd.edu>
dwalton1@bach.helios.nd.edu (david walton) writes:
> *Ethernet* addresses are assigned to the physical hardware on the card
> (which card may be moved around from machine to machine). *IP
> addresses* (which I think is what you mean)
Yea, I meant IP. I'm not a hardware person, so I had never heard of
Ethernet adresses on the cards and assumed that the "adress" mentioned
was an IP address.
Juan Ingles
<DACRXL01.OURX124@tcp30.dx.deere.com>
--
Proteus Ventures, Inc. - Computer Software Consulting and Development
1514 Oriole Ave * Waterloo, IA 50701 * (319) 232-0985
+++++++++++++++++++++++++++
>From Paul Ferguson <pferguson@kaleida.com>
Date: 9 Mar 1994 19:06:06 GMT
Organization: Kaleida Labs, Inc.
In article <2lk0v2$oq3@news.nd.edu> david walton,
dwalton1@bach.helios.nd.edu writes:
> Now that I think about it, it's not trivial to get the Ethernet
> address on built-in hardware if the machine doesn't have a
transceiver
> with an active link attached. (Is is possible to do this, BTW? I
> don't see any way of doing it by making MacTCP calls, but is there
a
> lower-level driver call that could return this information?)
Yes, there is a device driver call to the EtherTalk driver to
return the Ethernet address.
All Ethernet cards have their Ethernet address PROM memory mapped
into the physical address space, but there is no standard for where
this may be. Therefore, directly accessing the Ethernet address
is highly vendor dependent.
Also, there is a defined method for providing a "soft" Ethernet
address in a resource that will override the hardware Ethernet
address.
--fergy
- ------------------------------------------------------------------
Paul Ferguson | "It's a sick world, I'm a happy guy..."
pferguson@kaleida.com |
- ------------------------------------------------------------------
+++++++++++++++++++++++++++
>From DACRXL01.OURX124@tcp30.dx.deere.com (Juan Ingles)
Date: Wed, 9 Mar 1994 23:05:51 GMT
Organization: Proteus Ventures, Inc.
In article <2lkong$k0c@news.kth.se>
d88-jwa@mumrik.nada.kth.se (Jon Wdtte) writes:
> >The ethernet address would still be the same. The address is assigned
> >to the machine and not to the card. The address is kept by the Mac TCP
> >software. (and can ussually be typed in by the user)
>
> PLEASE get your facts straigt at least.
Hey! My facts were straight! I was just talking about something
completly different than everyone else was! That's all! :)
(Is that the Topic Police I hear coming?.....)
Juan Ingles
<DACRXL01.OURX124@tcp30.dx.deere.com>
--
Proteus Ventures, Inc. - Computer Software Consulting and Development
1514 Oriole Ave * Waterloo, IA 50701 * (319) 232-0985
--
Yes, I understand that you understood what I said. What you don't
understand is that I didn't say what I meant.
+++++++++++++++++++++++++++
>From peterb@tcc.oecn.ohio.gov (Peter Bierman)
Date: Sun, 13 Mar 1994 22:32:50 GMT
Organization: Linworth Alternative HS
In article <2lih8e$l5b@nigel.msen.com>, time@garnet.msen.com (Tim Endres)
wrote:
> I really like Ivan's idea of storing the time for the disk
> that the *app* is on. This solves Peter's network installation
> problems and it solves CD and server setups.
But what if the user transfers the app to a different volume because of low
disk space? I do this all the time.
--
Peter Bierman \ The Metropolis \ The most primitive part of
the
peterb@tcc.oecn.ohio.gov \ (614)-846-1911 \ the brain concerns
itself
\ 600MB Mac Files \ with the "Four F's":
"I've changed my mind, Hobbes \ FirstClass \ Feeding, Fighting,
Fleeing,
people are scum." --Calvin \ Mac & Windows \ and Reproduction.
+++++++++++++++++++++++++++
>From noah@apple.com (Noah Price)
Date: Thu, 10 Mar 1994 23:49:02 GMT
Organization: (not the opinions of) Apple Computer, Inc.
In article <CNjbKKKX.q3sn67@outpost.SF-Bay.org>, peirce@outpost.SF-Bay.org
(Michael Peirce) wrote:
> In article <1994Mar7.150036.11171@midway.uchicago.edu>, ajr3@quads.uchicago.edu (Alain Roy) writes:
> >
> > works unless you're like me: i have 2 hard drives. if every time i switched,
> > i had the copy protection of a program fire up, i'd be really upset.
>
> But this would only happen the first time you started up on your second
> disk. After that, its prefs file would contain the init time of *that*
> disk.
But what if he switches back and forth between the two disks often for
whatever reason?
noah
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Noah Price (not the opinions of) Apple Computer, Inc.
Macintosh AV Hardware 20525 Mariani Ave., MS 60-TNT
noah@apple.com Cupertino CA 95014
+++++++++++++++++++++++++++
>From zdelesde@vt.edu (Zac DeLesDernier)
Date: 18 Mar 1994 03:17:41 GMT
Organization: Virginia Tech
I have a related question. I need a way to uniquely identify a
file, other than its name. This identifying mechanism should also work
for copies of a file. (i.e. A backup would have the same file id.) The
id should _not_ change if the file is renamed or moved. (I hope I am
making myself clear.) One idea I had was writing some bignum into the
VERS resource, but then I dont want this marking system to mangle
applications (or anything else that might have a valid VERS resource.)
Any ideas?
- -
Zac DeLesDernier
zdelesde@vt.edu
---------------------------
>From bdiamand@netcom.com (Ben Diamand)
Subject: I know the Mac MM isn't reentrant, but:
Date: Thu, 10 Mar 1994 03:12:17 GMT
Organization: NETCOM On-line Communication Services (408 241-9760 guest)
I know the Mac MM isn't reentrant, but, can I call HUnlock from within an
interrupt(read:completion routine/callBack)? If the answer is no, would
some mac guru care to post/email a way to let the Mac Memory Manager know
that a handle no longer needs to locked? I realize it's been a long time
since the high byte was used for this purpose, but the same info's got to
be somewhere, right?! As a further question to the same person who tells
me how to change this(assuming anyone does :) ), am I doomed in
native/emulated PowerPC using whatever means you give me to change this
attribute?
Thanks!
Ben Diamand
bdiamand@netcom.com
ALINK:bdiamand
+++++++++++++++++++++++++++
>From resnick@cogsci.uiuc.edu (Pete Resnick)
Date: Wed, 09 Mar 1994 23:07:59 -0600
Organization: University of Illinois at Urbana-Champaign
In article <bdiamandCMFI8H.K7o@netcom.com>, bdiamand@netcom.com (Ben
Diamand) wrote:
>I know the Mac MM isn't reentrant, but, can I call HUnlock from within an
>interrupt(read:completion routine/callBack)?
HUnlock is not on the list of routines that cannot be called at interrupt
time. It should be safe.
pr
--
Pete Resnick (...so what is a mojo, and why would one be rising?)
Graduate assistant - Philosophy Department, Gregory Hall, UIUC
System manager - Cognitive Science Group, Beckman Institute, UIUC
Internet: resnick@cogsci.uiuc.edu
+++++++++++++++++++++++++++
>From bdiamand@netcom.com (Ben Diamand)
Date: Thu, 10 Mar 1994 07:25:56 GMT
Organization: NETCOM On-line Communication Services (408 241-9760 guest)
Pete Resnick (resnick@cogsci.uiuc.edu) wrote:
: In article <bdiamandCMFI8H.K7o@netcom.com>, bdiamand@netcom.com (Ben
: Diamand) wrote:
: >I know the Mac MM isn't reentrant, but, can I call HUnlock from within an
: >interrupt(read:completion routine/callBack)?
: HUnlock is not on the list of routines that cannot be called at interrupt
: time. It should be safe.
Thank-you for the reply...Ya, I know that it's not on the list. But, I
have great fear regarding interrupts and the MM, Sound Manager, and the
File Manager. They all use interrupts to get their respective jobs done
and they all are incorrectly documented with respect to interrupts in
various versions of IM. Sound Manager 3.0 seems to fix many problems that
I had with sound interrupts, but I stiil am very leary(sp?) of the Mac MM.
Maybe I'm a Unix person at heart? :)
Ben Diamand
bdiamand@netcom.com
ALINK:bdiamand
+++++++++++++++++++++++++++
>From gurgle@netcom.com (Pete Gontier)
Date: Thu, 10 Mar 1994 17:52:59 GMT
Organization: cellular
resnick@cogsci.uiuc.edu (Pete Resnick) writes:
>In article <bdiamandCMFI8H.K7o@netcom.com>, bdiamand@netcom.com (Ben
>Diamand) wrote:
>>I know the Mac MM isn't reentrant, but, can I call HUnlock from within an
>>interrupt(read:completion routine/callBack)?
>HUnlock is not on the list of routines that cannot be called at interrupt
>time. It should be safe.
Apple has now disowned that list. Apple says that although there are
traps which can be called at interrupt time, the list is out of date.
In particular, I can imagine HUnlock being one of the traps that would
fail or misbehave at interrupt time. If the handle's flags were kept
in a prefix to the buffer rather than in the master pointer list, the
Memory Manager could be in the middle of shuffling that block when
HUnlock occurred, and the master pointer might not be updated yet. I'm
not sure, but I think this may be possible in a 32-bit heap. In any
case, it's not something I would want to rely on. Apple is changing the
implementation of the Memory Manager under System 7 for PowerPC, which
means there will be at least 3 known major versions of the MM. Since the
MM is one of the most sensitive areas with regard to interrupt time, I
wouldn't push my luck.
But now I'm curious -- why would you want to unlock a handle at
interrupt time?
--
Pete Gontier, CTO, Integer Poet Software; gurgle@netcom.com
+++++++++++++++++++++++++++
>From ivanski@world.std.com (Ivan M CaveroBelaunde)
Date: Thu, 10 Mar 1994 15:28:20 GMT
Organization: The World Public Access UNIX, Brookline, MA
resnick@cogsci.uiuc.edu (Pete Resnick) writes:
>In article <bdiamandCMFI8H.K7o@netcom.com>, bdiamand@netcom.com (Ben
>Diamand) wrote:
>>I know the Mac MM isn't reentrant, but, can I call HUnlock from within an
>>interrupt(read:completion routine/callBack)?
>HUnlock is not on the list of routines that cannot be called at interrupt
>time. It should be safe.
Actually, the list is described as "routines that move memory." I don't
believe this implies that all other routines can be called at interrupt
time - certainly reentrancy can be an issue even for routines that do not
move memory. I'd be a little queasy about unlocking a handle from
interrupt time, for a couple of reasons:
o In the best of cases, that handle must be locked. It's
perfectly legal to unlock an unlocked handle, but
if done at interrupt time you would hose yourself
badly. I'd do an HGetState before that - of course,
I'm not sure whether it's safe to call HGetState
on an unlocked block during interrupt time in
the first place, so unless it's always locked or
you keep parallel state somewhere alse (ie global
storage) this becomes a catch-22.
o Non-reentrancy of the memory manager. I believe the memory manager
uses private pieces of low memory for temporary storage,
which might get nuked if you call HUnlock in the middle
of another mem mgr operation. Also, while I don't know
whether the "old" memory manager checks handle validity
on an HUnlock operation (by walking the free master pointer
lists, a no-no at interrupt time), the "new" memory manager
that has appeared on developer CDs in prerelease version
can be placed into a mode that performs that check.
o Patches. There are probably more than a few INITs/extensions out
there that patch HUnlock and do their own thing. While it
is completely illegal for them to move memory in their
patch, whether they could assume that the heaps are in
a consistent state (an invalid assumption at interrupt time)
is a gray area. Coupled with the fact that if your app
is incompatible with a popular extension, it will be your
app that is blamed, not that extension (unless the extension
is known as a particularly troublesome one), this'd make
me very wary.
For what it's worth, I wouldn't do it. I'd set a global flag and do it
from interrupt safe-land (like the event loop).
-Ivan
- -
Ivan Cavero Belaunde (ivanski@world.std.com)
Avid VideoShop Project Lead
Avid Technology, Inc.
+++++++++++++++++++++++++++
>From mgr@aggroup.aggroup.com (Mike Russell)
Date: Thu, 10 Mar 1994 12:05:29 -0800
Organization: the ag group, inc.
In article <bdiamandCMFI8H.K7o@netcom.com>, bdiamand@netcom.com (Ben
Diamand) wrote:
>
> I know the Mac MM isn't reentrant, but, can I call HUnlock from within an
> interrupt(read:completion routine/callBack)?
YOW - even if it's otherwise legal, consider the problems the following
non-interrupt code could run into if myHandle is unlocked asynchronously:
SignedByte s = HGetState(myHandle);
HLock(myHandle);
... Do some stuff ...
HSetState(myHandle, s);
So be very careful about who else might be looking at the locked block.
A safer way to do this - DTInstall(), IM V-467.
+++++++++++++++++++++++++++
>From resnick@cogsci.uiuc.edu (Pete Resnick)
Date: 11 Mar 1994 02:03:15 GMT
Organization: University of Illinois at Urbana
mgr@aggroup.aggroup.com (Mike Russell) writes:
>So be very careful about who else might be looking at the locked block.
>A safer way to do this - DTInstall(), IM V-467.
No, DTInstall won't help. Deferred tasks get executed at a time which
is effectively the same as interrupt time. It is no safer to call a
routine at deferred task time than at interrupt time.
pr
--
Pete Resnick (...so what is a mojo, and why would one be rising?)
Graduate assistant - Philosophy Department, Gregory Hall, UIUC
System manager - Cognitive Science Group, Beckman Institute, UIUC
Internet: resnick@cogsci.uiuc.edu
+++++++++++++++++++++++++++
>From resnick@cogsci.uiuc.edu (Pete Resnick)
Date: 11 Mar 1994 02:10:29 GMT
Organization: University of Illinois at Urbana
ivanski@world.std.com (Ivan M CaveroBelaunde) writes:
>Actually, the list is described as "routines that move memory."
No, the list at the end of the second edition of the X-Ref is
"routines that can't be called at interrupt." Some of them move
memory; some of them aren't reentrant.
pr
--
Pete Resnick (...so what is a mojo, and why would one be rising?)
Graduate assistant - Philosophy Department, Gregory Hall, UIUC
System manager - Cognitive Science Group, Beckman Institute, UIUC
Internet: resnick@cogsci.uiuc.edu
+++++++++++++++++++++++++++
>From quinn@cs.uwa.edu.au (Quinn "The Eskimo!")
Date: Fri, 11 Mar 1994 12:14:37 +0800
Organization: Department of Computer Science, The University of Western Australia
In article <resnick-090394230759@colt-17.slip.uiuc.edu>,
resnick@cogsci.uiuc.edu (Pete Resnick) wrote:
>In article <bdiamandCMFI8H.K7o@netcom.com>, bdiamand@netcom.com (Ben
>Diamand) wrote:
>
>>I know the Mac MM isn't reentrant, but, can I call HUnlock from within an
>>interrupt(read:completion routine/callBack)?
>
>HUnlock is not on the list of routines that cannot be called at interrupt
>time. It should be safe.
I hate to be picky but this is ***RONG!!!!***
If you don't believe me read Kon & Bal's puzzle page in develop 16.
Here's an extract....
- --------------------
Mike The interesting part of the heap before and after the
MoveHHi call is shown in the figure. Before MoveHHi there was a locked
block, labeled A in the figure, which is marked as relocatable afterward.
The relocatable block just below locked block B is getting overwritten by
the block we9re calling MoveHHi on.
KON MoveHHi works by first saving the contents of the block
that you9re moving, then marking the block as free. Then it calls
CompactMem on the heap, which bubbles all the free space up to any islands
and all relocatable blocks down. Then it copies the block to the free
block just before the island.
BAL And someone is coming in at interrupt time and unlocking
the island, block A in the figure. Instead of remembering the location of
the island, MoveHHi searches for it after the CompactMem call. Since that
block was unlocked by an interrupt after CompactMem, a different block is
found the second time. When MoveHHi backs up to the previous, presumably
free, block and starts copying data, the heap gets trashed.
Mike Yeah, that interrupt unlocking the block was QuickTime,
BAL. It turns out the Sound Manager does the same thing. Apparently the
3system architects2 at the time thought it was OK to call HUnlock on a
locked block during an interrupt. Not! We fixed it by deferring all
HUnlock calls until MoveHHi finishes. This was the cleanest fix; it keeps
us from patching out huge parts of the Memory Manager. But we were stumped
for quite a while.
KON Nasty.
BAL Yeah.
- --------------------
I'm sorry about the formatting but I cut and pasted it out of the
magazine on the CD. Please read the article for a better explanation.
--
Quinn "The Eskimo!" <quinn@cs.uwa.edu.au> "Support HAVOC!"
Department of Computer Science, The University of Western Australia
I hate newsreaders that complain about more quoted text than article
text. My quotes weren't from another article. Grrrrr!!!!!
+++++++++++++++++++++++++++
>From bdiamand@netcom.com (Ben Diamand)
Date: Fri, 11 Mar 1994 07:41:42 GMT
Organization: NETCOM On-line Communication Services (408 241-9760 guest)
Mike Russell (mgr@aggroup.aggroup.com) wrote:
: In article <bdiamandCMFI8H.K7o@netcom.com>, bdiamand@netcom.com (Ben
: Diamand) wrote:
: >
: > I know the Mac MM isn't reentrant, but, can I call HUnlock from within an
: > interrupt(read:completion routine/callBack)?
: YOW - even if it's otherwise legal, consider the problems the following
: non-interrupt code could run into if myHandle is unlocked asynchronously:
: SignedByte s = HGetState(myHandle);
: HLock(myHandle);
: ... Do some stuff ...
: HSetState(myHandle, s);
: So be very careful about who else might be looking at the locked block.
: A safer way to do this - DTInstall(), IM V-467.
My non-interrupt code locks the handle as soon as it gets it and then
'forgets' about the handle. The interrupt code handles the handles:)
Ben Diamand
bdiamand@netcom.com
ALINK:bdiamand
+++++++++++++++++++++++++++
>From bdiamand@netcom.com (Ben Diamand)
Date: Fri, 11 Mar 1994 07:46:12 GMT
Organization: NETCOM On-line Communication Services (408 241-9760 guest)
Quinn "The Eskimo! (quinn@cs.uwa.edu.au) wrote:
: In article <resnick-090394230759@colt-17.slip.uiuc.edu>,
: resnick@cogsci.uiuc.edu (Pete Resnick) wrote:
: >In article <bdiamandCMFI8H.K7o@netcom.com>, bdiamand@netcom.com (Ben
: >Diamand) wrote:
: >
: >>I know the Mac MM isn't reentrant, but, can I call HUnlock from within an
: >>interrupt(read:completion routine/callBack)?
: >
: >HUnlock is not on the list of routines that cannot be called at interrupt
: >time. It should be safe.
: I hate to be picky but this is ***RONG!!!!***
: If you don't believe me read Kon & Bal's puzzle page in develop 16. :
Here's an extract....
[text deleted]
: ----------------------
: Mike Yeah, that interrupt unlocking the block was QuickTime,
: BAL. It turns out the Sound Manager does the same thing. Apparently the
: 3system architects2 at the time thought it was OK to call HUnlock on a
: locked block during an interrupt. Not! We fixed it by deferring all
: HUnlock calls until MoveHHi finishes. This was the cleanest fix; it keeps
: us from patching out huge parts of the Memory Manager. But we were stumped
: for quite a while.
: KON Nasty.
: BAL Yeah.
: ----------------------
: I'm sorry about the formatting but I cut and pasted it out of the
: magazine on the CD. Please read the article for a better explanation.
: --
: Quinn "The Eskimo!" <quinn@cs.uwa.edu.au> "Support HAVOC!"
: Department of Computer Science, The University of Western Australia
: I hate newsreaders that complain about more quoted text than article
: text. My quotes weren't from another article. Grrrrr!!!!!
Ok, now here's a stupid question. How does one know when MoveHHi is done?
I don't mind terribly defering the HUnlock...I just wanted to know if I
had to...Thanks forthe reply...
Ben Diamand
bdiamand@netcom.com
ALINK:bdiamand
+++++++++++++++++++++++++++
>From Duane Murphy <damurphy@wc.novell.com>
Date: Mon, 14 Mar 1994 16:14:32 GMT
Organization: Novell, Inc.
In article <bdiamandCMFI8H.K7o@netcom.com> Ben Diamand,
bdiamand@netcom.com writes:
>I know the Mac MM isn't reentrant, but, can I call HUnlock from within
an
>interrupt(read:completion routine/callBack)? If the answer is no, would
Ben,
There is a great article in develop issue 16 in KON & BAL's Puzzle Page
that talks about just this problem. I just read it last week. Even the
guru's at Apple think that HUnlock can be called at interrupt time.
The problem stems from the algorithm used for MoveHHI. I don't
quite understand it enough to explain it, but if the handle gets unlocked
at the wrong time then MoveHHI will overwrite the handle.
Check out the article, it is pretty interesting (especially for debugging
techniques).
Later,
...Duane
+------------------------+--------------------------------------------+
| Duane Murphy | My opinions are mine, mine, and only mine; |
| damurphy@wc.novell.com | Except when they are also yours. |
+------------------------+--------------------------------------------+
+++++++++++++++++++++++++++
>From Steve Ethier <ethier@wc.novell.com>
Date: Mon, 14 Mar 1994 18:03:43 GMT
Organization: Novell, Inc.
In article <1994Mar14.161432.18054@novell.com> Duane Murphy,
damurphy@wc.novell.com writes:
>In article <bdiamandCMFI8H.K7o@netcom.com> Ben Diamand,
>bdiamand@netcom.com writes:
>>I know the Mac MM isn't reentrant, but, can I call HUnlock from within
>an
>>interrupt(read:completion routine/callBack)? If the answer is no,
would
>Ben,
>There is a great article in develop issue 16 in KON & BAL's Puzzle Page
>that talks about just this problem. I just read it last week. Even the
>guru's at Apple think that HUnlock can be called at interrupt time.
>
>The problem stems from the algorithm used for MoveHHI. I don't
>quite understand it enough to explain it, but if the handle gets
unlocked
>at the wrong time then MoveHHI will overwrite the handle.
>
>Check out the article, it is pretty interesting (especially for
debugging
>techniques).
>
>Later,
>...Duane
Ben, the "short form" to Duane's answer is that HUnlock is *not* safe to
call at interrupt time. (Duane let me read the article, and I must admit
that it is indeed very interesting.)
Steve Ethier
ethier@wc.novell.com
+++++++++++++++++++++++++++
>From David A Lyons <dlyons@apple.com>
Date: Thu, 10 Mar 1994 22:26:21 GMT
Organization: Apple Computer, Inc.
In article <gurgleCMGn0B.F87@netcom.com> Pete Gontier,
gurgle@netcom.com writes:
> In particular, I can imagine HUnlock being one of the traps that
would
> fail or misbehave at interrupt time.
Correct, calling HUnlock at interrupt time is bad. See Kon and Bal's
Puzzle Page in _develop_ #16 (December 1993).
Dave Lyons, dlyons@apple.com
Mr Tangent
My opinions are my own, not Apple's.
---------------------------
>From mahboud@aggroup.com (Mahboud Zabetian)
Subject: If you use SysBeep() for debugging...
Date: Wed, 23 Feb 1994 15:07:55 -0800
Organization: AG Group, Inc.
If you're like me and like to throw in SysBeep() calls in questionable code
to help determine program flow, be careful!
SysBeep() may move memory and could potentially make dereferenced handles
invalid!
This is a hard one to chase down, since you now have another bug added to
whatever bug you were originally looking for.
Hope this helps someone.
-mahboud
- -------------------------------------------------------------
Mahboud Zabetian
mahboud@aggroup.com
ag group, inc.
2540 camino diablo, suite 200
walnut creek, ca 94596
510-937-7900 voice
510-937-2479 fax
510-937-6704 ara
ftp.aggroup.com anonymous ftp
+++++++++++++++++++++++++++
>From blume@twg.com (David Blume)
Date: Wed, 23 Feb 1994 23:56:35 GMT
Organization: Gokuraku Videos - Wollongong Dept.
mahboud@aggroup.com (Mahboud Zabetian) wrote:
>If you're like me and like to throw in SysBeep() calls in questionable code
>to help determine program flow, be careful!
>
>SysBeep() may move memory and could potentially make dereferenced handles
>invalid!
According to IM2, SysBeep() is stack-based. Also, my handy-dandy Online
reference doesn't have the diamond character indicating that it moves
memory.
However, 411 does agree with Mahboud. It says that SysBeep() does move
or purge memory. Sneaky...
--David
+-------------------------------------------------------------------------+
| David Blume | "A, Ayukawa!" | "Moemichan! ... SUKIDA!!" -- Youta |
| blume@twg.com | "Kasuga-kuun..." | "Suckerfish!" -- Ai Amano |
+-------------------------------------------------------------------------+
+++++++++++++++++++++++++++
>From danprice@delphi.com
Date: Wed, 23 Feb 94 19:51:33 -0500
Organization: Delphi (info@delphi.com email, 800-695-4005 voice)
Wow, good point. Any suggestions for an easy debugging tool like sysbeep()?
Has anyone had a problem w/ sysbeep() doing this?
-dp
+++++++++++++++++++++++++++
>From mahboud@aggroup.com (Mahboud Zabetian)
Date: Wed, 23 Feb 1994 22:51:49 -0800
Organization: AG Group, Inc.
In article <1994Feb23.235635.17269@twg.com>, blume@twg.com (David Blume)
wrote:
> mahboud@aggroup.com (Mahboud Zabetian) wrote:
> >If you're like me and like to throw in SysBeep() calls in questionable code
> >to help determine program flow, be careful!
> >
> >SysBeep() may move memory and could potentially make dereferenced handles
> >invalid!
>
> According to IM2, SysBeep() is stack-based. Also, my handy-dandy Online
> reference doesn't have the diamond character indicating that it moves
> memory.
>
Back in the days of the 128K and 512K mac, SysBeep() just played a good ole
beep. A tone.
Now that it plays digitized sounds, it seems to do a GetResource and/or
LoadResource to get the sound. You can verify with an A-Trap break (Don't
ATB on GetResource; Do an ATb for SysBeep, then when you are in the
debugger, setup an ATB GetResource. You'll see 'snd ' on the stack).
> However, 411 does agree with Mahboud. It says that SysBeep() does move
> or purge memory. Sneaky...
>
> --David
> +-------------------------------------------------------------------------+
> | David Blume | "A, Ayukawa!" | "Moemichan! ... SUKIDA!!" -- Youta |
> | blume@twg.com | "Kasuga-kuun..." | "Suckerfish!" -- Ai Amano |
> +-------------------------------------------------------------------------+
Sneaky is right. I was been bitten by this one 3 years ago too. Hard to
figure out.
-mahboud
- -------------------------------------------------------------
Mahboud Zabetian
mahboud@aggroup.com
ag group, inc.
2540 camino diablo, suite 200
walnut creek, ca 94596
510-937-7900 voice
510-937-2479 fax
510-937-6704 ara
ftp.aggroup.com anonymous ftp
+++++++++++++++++++++++++++
>From mahboud@aggroup.com (Mahboud Zabetian)
Date: Wed, 23 Feb 1994 22:58:58 -0800
Organization: AG Group, Inc.
In article <xu5p+Bd.danprice@delphi.com>, danprice@delphi.com wrote:
>
> Wow, good point. Any suggestions for an easy debugging tool like sysbeep()?
>
> Has anyone had a problem w/ sysbeep() doing this?
>
> -dp
Here's one way that I am trying out, but it's not audible like SysBeep().
I start at one end of my window and turn a pixel on. Using SetCPixel, I
can setup the color too.
I was mainly interested in doing this from an interrupt handler (I never
checked to see if it moved memory, sorry), and it seemed to work fine,
except that it was slow compared to my interrupt handler, and was slowing
everything down.
Are there still LowMem globals reserved for apps to use? If so, maybe the
application under test could write a status value into that global, and can
be checked at a later time?
Any other thoughts appreciated...
-mahboud
- -------------------------------------------------------------
Mahboud Zabetian
mahboud@aggroup.com
ag group, inc.
2540 camino diablo, suite 200
walnut creek, ca 94596
510-937-7900 voice
510-937-2479 fax
510-937-6704 ara
ftp.aggroup.com anonymous ftp
+++++++++++++++++++++++++++
>From pottier@corvette.ens.fr (Francois Pottier)
Date: 24 Feb 1994 10:39:07 GMT
Organization: Ecole Normale Superieure, PARIS, France
In article <mahboud-230294225858@mahboud.aggroup.com>,
Mahboud Zabetian <mahboud@aggroup.com> wrote:
>> Wow, good point. Any suggestions for an easy debugging tool like sysbeep()?
Why not use the DebugStr call ?
For instance, if I'm not mistaken, DebugStr('Checkpoint 1 ; g');
should print "Checkpoint 1" into Macsbug and resume execution.
--
Francois Pottier ___ ___ _ _ / ___ ___ ___
pottier@dmi.ens.fr /_ /__/ /_| /| / / / / / / /__
/ / \ / | / |/ /___ /__/ / ___/ _
/
+++++++++++++++++++++++++++
>From tzs@u.washington.edu (Tim Smith)
Date: 24 Feb 1994 10:43:04 GMT
Organization: University of Washington School of Law, Class of '95
In article <xu5p+Bd.danprice@delphi.com>, <danprice@delphi.com> wrote:
>Wow, good point. Any suggestions for an easy debugging tool like sysbeep()?
One thing I found real useful for debugging was to write my own printf
that wrote directly to screen memory. It used a simple built in font
(with each character being 3x5--yes, you can actually make a legible
character set with 3x5--so that the memory manipulation would be easy).
With this, I could get debugging information from all kinds of places
where regular debug tools might fail: ethernet interrupt routines,
SCSI boot code, Nubus card interrupts, etc., and I didn't have to
worry about memory being moved, or managers not being in the proper
state, or whatever.
Unfortunately, I wrote this as part of my job, so I can't post it.
--Tim Smith
+++++++++++++++++++++++++++
>From kledbetter@aol.com (KLedbetter)
Date: 24 Feb 1994 13:34:01 -0500
Organization: America Online, Inc.
>>Wow, good point. Any suggestions for an easy debugging tool like
>> sysbeep()?
Well, if you're using C and System 7, you might want to look for my program
"DebugWindow 2.0". It uses AppleEvents to easily display messages in a
debugging window. Simply add DebugWindow.Lib to your project, and then you can
do things like:
Debug ("Just starting so-and-so routine\r");
.....
Debug ("Value of index is now %d\r", index);
Keith
+++++++++++++++++++++++++++
>From perlis_a@math.lsu.edu (Alexander Perlis)
Date: 25 Feb 1994 00:47:14 GMT
Organization: Louisiana State University InterNetNews Site
In article <1994Feb23.235635.17269@twg.com> blume@twg.com (David Blume)
writes:
> mahboud@aggroup.com (Mahboud Zabetian) wrote:
> >If you're like me and like to throw in SysBeep() calls in questionable
code
> >to help determine program flow, be careful!
> >
> >SysBeep() may move memory and could potentially make dereferenced
handles
> >invalid!
>
> According to IM2, SysBeep() is stack-based. Also, my handy-dandy Online
> reference doesn't have the diamond character indicating that it moves
> memory.
>
> However, 411 does agree with Mahboud. It says that SysBeep() does move
> or purge memory. Sneaky...
>
> --David
I would presume that this inconsistency in the documentation has to do
with changes to the SysBeep() trap after the Sound Manager was added to
the system software a few years back. At that point, SysBeep() no longer
accessed the speaker or low-level sound routines directly, but instead
called the Sound Manager to play the current system beep sound. The Sound
Manager, being complicated and supporting different sounds stored in
various formats in resources, obviously moves memory to do its work.
At one point (when the Sound Manager first came out) it was still possible
to call the original SysBeep() code. At least, if "System Beep" was the
system beep sound, then SysBeep() would use its old code rather than
calling the Sound Manager. In today's system software, however, there is
an actual sound called "System Beep" and it gets played by the Sound
Manager if it is the selected system beep sound. [Boy, this sounds like a
bunch of double-talk. Is anyone able to follow this?]
Presumably, if the code of the original SysBeep() routine is still in ROM,
one can call it somehow, and memory will not be moved. That would solve
the problem of using beep sounds while debugging code which cannot move
memory. I don't know how to call the original SysBeep() code, assuming it
is even possible. Can any of the experts reading this thread shed some
light on the matter?
Alexander Perlis, perlis_a@math.lsu.edu
+++++++++++++++++++++++++++
>From robert@tbit.com (RObert Abatecola)
Date: Thu, 24 Feb 94 17:55:06 PST
Organization: TBIT, WMCS chat/message BBS, San Jose, CA (408)257-6225
> Well, if you're using C and System 7, you might want to look for my program
> "DebugWindow 2.0". It uses AppleEvents to easily display messages in a
> debugging window. Simply add DebugWindow.Lib to your project, and then you
> can
> do things like:
>
> Debug ("Just starting so-and-so routine\r");
> .....
> Debug ("Value of index is now %d\r", index);
Any hints on where one might look for DebugWindow 2.0?
+++++++++++++++++++++++++++
>From pjcreath@tucson.Princeton.EDU (Peter Janssen Creath)
Date: Thu, 24 Feb 1994 21:10:06 GMT
Organization: Princeton University
In article <xu5p+Bd.danprice@delphi.com>, <danprice@delphi.com> wrote:
>Wow, good point. Any suggestions for an easy debugging tool like sysbeep()?
My personal favorite is MacsBug in conjunction with Debugger() or
DebugStr("\pWhatever error message I want");
And it's free...(just hit "g" to resume)
And unless you're fiddling with low memory (and hosing the interrupt
table) it won't crash on you...
+++++++++++++++++++++++++++
>From blume@twg.com (David Blume)
Date: Fri, 25 Feb 1994 16:34:03 GMT
Organization: Gokuraku Videos - Wollongong Dept.
tzs@u.washington.edu (Tim Smith) wrote:
>One thing I found real useful for debugging was to write my own printf
>that wrote directly to screen memory. ... I didn't have to
>worry about memory being moved, or managers not being in the proper
>state, or whatever.
How did you draw characters directly to the screen without using a toolbox
routine that may have moved or purged memory? Everything from DrawChar()
to CopyBits() might move memory...
--David
+---------------------------------------------------------------+
| David Blume | "I get tired thinking of all the things I |
| blume@twg.com | don't want to do." --Bukowski, _Barfly_ |
+---------------------------------------------------------------+
+++++++++++++++++++++++++++
>From bc@wetware.com (monsieur HAINEUX)
Date: Fri, 25 Feb 1994 19:20:09 GMT
Organization: /usr/local/lib/rn/organization
|In article <xu5p+Bd.danprice@delphi.com>, <danprice@delphi.com> wrote:
|>Wow, good point. Any suggestions for an easy debugging tool like sysbeep()?
Use DebugStr(). Unless there's a reason you can't use MacsBug[1], it
works like a champ, and you get more feedback than SysBeep.
If you're REALLY clever, you can use a macro that includes an #ifdef
_DEBUG_ to automatically make the DebugStr's go away for production
code.
bill coderre
[1] Yes, there are cases where you cannot use MacsBug. Pray that they
never catch up to you.
+++++++++++++++++++++++++++
>From mahboud@aggroup.com (Mahboud Zabetian)
Date: Fri, 25 Feb 1994 12:16:16 -0800
Organization: AG Group, Inc.
In article <CLsoDL.Exu@wetware.com>, bc@wetware.com (monsieur HAINEUX)
wrote:
> |In article <xu5p+Bd.danprice@delphi.com>, <danprice@delphi.com> wrote:
> |>Wow, good point. Any suggestions for an easy debugging tool like sysbeep()?
>
> Use DebugStr(). Unless there's a reason you can't use MacsBug[1], it
> works like a champ, and you get more feedback than SysBeep.
>
I do use Debugger() and DebugStr(). (In fact I also have use my own
DebugNum(), DebugHexNum() DebugBuffStr()....).
Yet there have been times that a SysBeep() is best. For example: A
customer complains that our applications doesn't do x. I look and look and
look and look at the code and wonder: does it get to x and doesn't execute
it, or does it execute x and x is the problem, or is this user on drugs
since the code is OBVIOUSLY correct? (I don't write buggy code :-) Well, I
add a quick SysBeep() before x and in x. Then I send it to the customer
(who may or may not have MacsBug or who may or may not know what to do when
in MacsBug) and ask him: "Does it beep when you try it? Once or twice?"
You see, a Debugger() call would probably have been more of a hassle.
-mahboud
ps. My favorite bug:
handle = GetResource(.....);
if (handle = nil) {
// resource is there so do somthing with it.
}
My next favorite bug:
Calling InvalRect without a valid GrafPort set.
And:
SetPort(window); // where window is a random, garbage value on the
stack
- -------------------------------------------------------------
Mahboud Zabetian
mahboud@aggroup.com
ag group, inc.
2540 camino diablo, suite 200
walnut creek, ca 94596
510-937-7900 voice
510-937-2479 fax
510-937-6704 ara
ftp.aggroup.com anonymous ftp
+++++++++++++++++++++++++++
>From bc@wetware.com (monsieur HAINEUX)
Date: Fri, 25 Feb 1994 21:34:25 GMT
Organization: /usr/local/lib/rn/organization
In article <CLsoDL.Exu@wetware.com> bc@wetware.com (monsieur HAINEUX) writes:
||In article <xu5p+Bd.danprice@delphi.com>, <danprice@delphi.com> wrote:
||>Wow, good point. Any suggestions for an easy debugging tool like sysbeep()?
|
|Use DebugStr(). Unless there's a reason you can't use MacsBug[1], it
|works like a champ, and you get more feedback than SysBeep.
|
|If you're REALLY clever, you can use a macro that includes an #ifdef
|_DEBUG_ to automatically make the DebugStr's go away for production
|code.
|
|bill coderre
|[1] Yes, there are cases where you cannot use MacsBug. Pray that they
|never catch up to you.
Think Reference reminded me that DebugStr dumps you into the debugger,
but you can put a string like "Entering BugVille;g" and the semicolon
allows you to load up the rest of the string with MacsBug commands. In
this case, the screen will flicker briefly while Macsbug writes the
line, then the program will resume.
bill coderre
"Hard Problems made simple -- and vice versa"
-- corporate motto of Symbolics
+++++++++++++++++++++++++++
>From mxmora@unix.sri.com (Matt Mora)
Date: 25 Feb 1994 10:08:13 -0800
Organization: SRI International, Menlo Park, CA
In article <1994Feb25.163403.14920@twg.com> blume@twg.com (David Blume) writes:
>tzs@u.washington.edu (Tim Smith) wrote:
>>One thing I found real useful for debugging was to write my own printf
>>that wrote directly to screen memory. ... I didn't have to
>>worry about memory being moved, or managers not being in the proper
>>state, or whatever.
>
>How did you draw characters directly to the screen without using a toolbox
>routine that may have moved or purged memory? Everything from DrawChar()
>to CopyBits() might move memory...
He probably twiddled the bits directly. Which is why he said he was using
a 5 x 7 character set. He set each bit in the screen's bitmap himself.
Cool.
Xavier
--
___________________________________________________________
Matthew Xavier Mora Matt_Mora@qm.sri.com
SRI International mxmora@unix.sri.com
333 Ravenswood Ave Menlo Park, CA. 94025
+++++++++++++++++++++++++++
>From monroe@teleport.com (Monroe Williams)
Date: 25 Feb 1994 17:00:18 -0800
Organization: Teleport - Portland's Public Access (503) 220-1016
In article <2kjhqi$2n70@te6000.otc.lsu.edu>,
Alexander Perlis <perlis_a@math.lsu.edu> wrote:
[...]
>Presumably, if the code of the original SysBeep() routine is still in ROM,
>one can call it somehow, and memory will not be moved. That would solve
>the problem of using beep sounds while debugging code which cannot move
>memory. I don't know how to call the original SysBeep() code, assuming it
>is even possible. Can any of the experts reading this thread shed some
>light on the matter?
I doubt very much that any of the newer machines have the old SysBeep
code in them. As you said, it's been done through the sound manager
for quite some time now.
However...
It should be possible to find the startup chime code in the ROMs. I
seem to remember a little utility that plays the startup chime and
various error tones, apparently using the ROMs to do it. Does anybody
out there know how this is done? There are a couple of really
disturbing sounds a Mac can make (like when it fails the hardware RAM
diagnostic) that would definitely get your attention. I can't imagine
these ROM routines would even require the memory manager, much less
move memory.
BTW (for the curious), on my SE/30 you can hear the error tones by
pressing the interrupt button on the programmer's switch while the
machine is doing the initial memory tests when you first switch it on.
I don't know if this trick works on newer machines that have the nicer
sounding startup chime, though.
- monroe
--
monroe@teleport.COM Public Access User --- Not affiliated with TECHbooks
Public Access UNIX and Internet at (503) 220-0636 (1200/2400, N81)
+++++++++++++++++++++++++++
>From monroe@teleport.com (Monroe Williams)
Date: 25 Feb 1994 17:22:04 -0800
Organization: Teleport - Portland's Public Access (503) 220-1016
In article <CLsuLE.LBM@wetware.com>, monsieur HAINEUX <bc@wetware.com> wrote:
>In article <CLsoDL.Exu@wetware.com> bc@wetware.com (monsieur HAINEUX) writes:
>|If you're REALLY clever, you can use a macro that includes an #ifdef
>|_DEBUG_ to automatically make the DebugStr's go away for production
>|code.
Digressing just a bit...
It's pretty simple to make up a version of assert() that uses
DebugStr. (Start with the assert.h that comes with your development
environment. It's almost always implemented as a macro.) With a few
preprocessor tricks, it will give you the file name and line number, as
well as the expression inside the assertion. Real handy, especially
for porting code from unix that's full of asserts, when you're not
using console I/O.
- monroe
--
monroe@teleport.COM Public Access User --- Not affiliated with TECHbooks
Public Access UNIX and Internet at (503) 220-0636 (1200/2400, N81)
+++++++++++++++++++++++++++
>From lewistot@netcom.com (John Lewis)
Date: Sat, 26 Feb 1994 04:22:56 GMT
Organization: NETCOM On-line Communication Services (408 241-9760 guest)
Mahboud Zabetian (mahboud@aggroup.com) wrote:
: SysBeep() may move memory and could potentially make dereferenced handles
: invalid!
You mean you don't lock your handles BEFORE you dereference them?
: This is a hard one to chase down, since you now have another bug added to
: whatever bug you were originally looking for.
Surround your dereferences with a LockHandle/UnlockHandle pair. This is
not only good programming practice, but it will also solve the problem
of SysBeep moving things around.
--
- -------------------------------------------------------------------------
John "I'ld rather be skydiving" Lewis|#include "standard .sig BS" |Witty |
lewistot@netcom.com <- prefered |Blue Skies to all skydivers.|text |
jlewis@maxis.com <- work |USPA 87419, C-22826 |picture|
lewistotle@aol.com |<Fnord> |comming|
+++++++++++++++++++++++++++
>From kledbetter@aol.com (KLedbetter)
Date: 26 Feb 1994 13:25:02 -0500
Organization: America Online, Inc.
> Debug ("Just starting so-and-so routine\r");
> .....
> Debug ("Value of index is now %d\r", index);
Any hints on where one might look for DebugWindow 2.0?
- --------
Robert --
it's available on Compuserve in the MacDev forum, and on America Online in
the Mac Developers area. It works really nice .. you can also do Hex dumps to
the window (ie: DebugHexDump (myBuffer, 1024)) and then print out the window's
contents, save as a teachtext document, etc..
Keith
+++++++++++++++++++++++++++
>From casgrain@ERE.UMontreal.CA (Casgrain Philippe)
Date: Sat, 26 Feb 1994 19:53:59 GMT
Organization: Universite de Montreal
>> Debug ("Just starting so-and-so routine\r");
>> .....
>> Debug ("Value of index is now %d\r", index);
>
>Any hints on where one might look for DebugWindow 2.0?
> it's available on Compuserve in the MacDev forum, and on America Online in
>the Mac Developers area. It works really nice .. you can also do Hex dumps to
>the window (ie: DebugHexDump (myBuffer, 1024)) and then print out the window's
>contents, save as a teachtext document, etc..
>
Any idea where we could find it on the Internet? could somebody post it?
Philippe
--
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Philippe Casgrain Etudiant-Chercheur Casgrain@ERE.UMontreal.CA
Departement des Sciences Biologiques Universite de Montreal
"Imitation is the sincerest form of flattery"
+++++++++++++++++++++++++++
>From kledbetter@aol.com (KLedbetter)
Date: 27 Feb 1994 01:35:01 -0500
Organization: America Online, Inc.
>
Any idea where we could find it on the Internet? could somebody post it?
Philippe
- -------
I'm looking into getting it up on the Internet now...I'll post a message as
soon as I get it out there...
keith
+++++++++++++++++++++++++++
>From tzs@u.washington.edu (Tim Smith)
Date: 1 Mar 1994 03:24:34 GMT
Organization: University of Washington School of Law, Class of '95
In article <2kleqd$51q@unix.sri.com>, Matt Mora <mxmora@unix.sri.com> wrote:
>He probably twiddled the bits directly. Which is why he said he was using
>a 5 x 7 character set. He set each bit in the screen's bitmap himself.
>Cool.
Actually, I said 3x5. That way, with one pixel between consecutive characters,
memory manipulation only had to go down to the nibble level. On a 640x480
display, with 2 lines of leading between lines, I could get 160 columns and
68 rows.
In addition to drawing the character, I would also draw an underline three
lines below the character, and erase the two lines immediately below the
character. That way, you could tell which of the 68 rows was the last one
drawn--it was the one that was underlined. That way you can tell where you
are as more than 68 rows are printed and they start to wrap. I also had an
end of line marker so you could tell on a row which characters belonged to
that row, and which were left over from the 68th previous printf, the 136th
previous printf, etc.
The hardest part was coming up with a 3x5 'M' that looks different than
a 3x5 'N'! Here's my character set, in case anyone is curious.
struct OneChar
{
char data[5]; /* the data for a character */
};
struct OneChar CharData[] =
{
{5,2,5,2,5}, /* non-existant char */
{2,5,7,5,5}, /* 1 A */
{6,5,6,5,6},
{7,5,4,5,7},
{6,5,5,5,6},
{7,4,6,4,7},
{7,4,6,4,4},
{7,4,5,5,7}, /* 7 G */
{5,5,7,5,5},
{7,2,2,2,7},
{3,1,1,5,7},
{4,5,6,5,5},
{4,4,4,4,7},
{5,7,5,5,5},
{5,7,7,7,5},
{2,5,5,5,2}, /* 15 O */
{7,5,7,4,4},
{2,5,5,7,3},
{6,5,7,6,5},
{3,4,6,1,7},
{7,2,2,2,2},
{5,5,5,5,7},
{5,5,5,5,2},
{5,5,5,7,5},
{5,2,2,2,5},
{5,5,2,2,2},
{7,1,2,4,7}, /* 26 Z */
{3,5,5,5,6}, /* 27 0 */
{2,6,2,2,7},
{7,5,2,4,7},
{7,1,3,1,7},
{5,5,7,1,1},
{7,4,7,1,7},
{4,4,7,5,7},
{7,1,1,2,2},
{7,5,7,5,7},
{7,5,7,1,1}, /* 36 9 */
{0,0,0,0,0}, /* 37 space */
{2,2,2,0,2}, /* ! */
{5,5,0,0,0}, /* " */
{5,7,5,7,5}, /* 40 # */
{7,6,2,3,7}, /* $ */
{3,3,2,6,6}, /* % */
{6,5,2,5,7}, /* & */
{2,2,0,0,0}, /* ' */
{2,4,4,4,2}, /* 45 ( */
{2,1,1,1,2}, /* ) */
{5,2,7,2,5}, /* * */
{0,2,7,2,0}, /* + */
{0,0,0,1,3}, /* , */
{0,0,7,0,0}, /* 50 - */
{0,0,0,6,6}, /* . */
{1,1,2,2,4}, /* / */
{6,6,0,6,6}, /* : */
{6,6,0,2,6}, /* ; */
{1,2,4,2,1}, /* 55 < */
{0,7,0,7,0}, /* = */
{4,2,1,2,4}, /* > */
{6,1,2,0,2}, /* ? */
{6,4,4,4,6}, /* [ */
{4,4,2,2,1}, /* 60 \ */
{3,1,1,1,3}, /* ] */
{2,5,0,0,0}, /* ^ */
{0,0,0,0,7}, /* _ */
{4,2,0,0,0}, /* ^ */
{3,2,4,2,3}, /* 65 { */
{2,2,2,2,2}, /* | */
{6,2,1,2,6}, /* } */
{4,7,1,0,0}, /* ~ */
{0,3,5,6,3}, /* @ */
{7,7,7,7,7} /* end of line marker */
}
--Tim Smith
+++++++++++++++++++++++++++
>From ez006626@othello.ucdavis.edu (David Xavier Clancy)
Date: Tue, 1 Mar 1994 09:51:29 GMT
Organization: University of California, Davis
I thought the accepted thing was to use FlashMenuBar
It is not auditory, but if you are looking at the screen, it does the trick.
Also, I'm pretty sure DebugWindow, (i get the name right?) mentioned in other
posts is at sumex.
--xav
+++++++++++++++++++++++++++
>From philip@concave.cs.wits.ac.za (Philip Machanick)
Date: Tue, 01 Mar 1994 08:51:39 +0200
Organization: Computer Science Dept, U of Witwatersrand
In article <lewistotCLtDIA.C3@netcom.com>, lewistot@netcom.com (John Lewis)
wrote:
> Surround your dereferences with a LockHandle/UnlockHandle pair. This is
> not only good programming practice, but it will also solve the problem
> of SysBeep moving things around.
No it's not. Much better practice is
oldstate = HGetState(h);
HLock(h);
...do something assuming h can't move...
HSetState(h, oldstate);
otherwise you could end up unlocking a handle that the code that called the
current routine still expects to have locked.
In any case: there are situations where you don't want to lock a handle and
to put the locking code in just because you are debugging is not a good
solution.
--
Philip Machanick philip@concave.cs.wits.ac.za
Department of Computer Science, University of the Witwatersrand
2050 Wits, South Africa
phone 27(11)716-3309 fax 27(11)339-7965
+++++++++++++++++++++++++++
>From walrathw@rferl.org (WalrathW)
Date: 3 Mar 94 09:22:38 -0500
Organization: RFE/RL Inc.
In article <lewistotCLtDIA.C3@netcom.com>
lewistot@netcom.com (John Lewis) writes:
> Mahboud Zabetian (mahboud@aggroup.com) wrote:
> : SysBeep() may move memory and could potentially make dereferenced handles
> : invalid!
>
> You mean you don't lock your handles BEFORE you dereference them?
>
> : This is a hard one to chase down, since you now have another bug added to
> : whatever bug you were originally looking for.
>
> Surround your dereferences with a LockHandle/UnlockHandle pair. This is
> not only good programming practice, but it will also solve the problem
> of SysBeep moving things around.
> --
I would disagree that it's good programming practice to just surround
every handle with HLock/HUnlock calls. Those calls take time and if
they aren't absolutely necessary, then you shouldn't use them.
HLock(myHandle);
((MyStruct*)*myHandle)->myLong = 10;
HUnlock(myHandle);
nahhh?
> ---------------------------------------------------------------------------
> John "I'ld rather be skydiving" Lewis|#include "standard .sig BS" |Witty |
> lewistot@netcom.com <- prefered |Blue Skies to all skydivers.|text |
> jlewis@maxis.com <- work |USPA 87419, C-22826 |picture|
> lewistotle@aol.com |<Fnord> |comming|
maxis.com, is that the Simulation Games company?
______o0o______
Wayne Walrath
RFE/RL Inc.
+++++++++++++++++++++++++++
>From tgreen@ersys.edmonton.ab.ca (Terry Greeniaus)
Date: Mon, 07 Mar 94 16:13:55 MST
Organization: Edmonton Remote Systems #2
> In article <mahboud-230294225858@mahboud.aggroup.com>,
> Mahboud Zabetian <mahboud@aggroup.com> wrote:
>
> >> Wow, good point. Any suggestions for an easy debugging tool like sysbeep(
Well, you could use FlashMenuBar(), but I'm not sure whether it messes
with memory or not.
--
Terry Greeniaus tgreen@ersys.edmonton.ab.ca
Edmonton Remote Systems Serving Edmonton/Northern Alberta since 1982
+++++++++++++++++++++++++++
>From mxmora@unix.sri.com (Matt Mora)
Date: 10 Mar 1994 09:00:10 -0800
Organization: SRI International, Menlo Park, CA
In article <wPBuic1w165w@ersys.edmonton.ab.ca> tgreen@ersys.edmonton.ab.ca (Terry Greeniaus) writes:
>> In article <mahboud-230294225858@mahboud.aggroup.com>,
>> Mahboud Zabetian <mahboud@aggroup.com> wrote:
>
>Well, you could use FlashMenuBar(), but I'm not sure whether it messes
>with memory or not.
Not unless you are sure the gworld is valid ( ie the one with the menubar)
before you call it as another poster had mentioned.
Xavier
--
___________________________________________________________
Matthew Xavier Mora Matt_Mora@qm.sri.com
SRI International mxmora@unix.sri.com
333 Ravenswood Ave Menlo Park, CA. 94025
+++++++++++++++++++++++++++
>From mbabramo@unix.amherst.edu (MICHAEL BERNARD ABRAMOWICZ)
Date: 11 Mar 1994 20:15:35 -0500
Organization: Amherst College, Amherst MA, USA
> Well, you could use FlashMenuBar(), but I'm not sure whether it messes
> with memory or not.
This is exactly the solution. FlashMenuBar() does NOT move memory.
> --
> Terry Greeniaus tgreen@ersys.edmonton.ab.ca
> Edmonton Remote Systems Serving Edmonton/Northern Alberta since 1982
Michael Abramowicz
Amherst College
Writer, Inside Macintosh: Memory, More Macintosh Toolbox, Sound
+++++++++++++++++++++++++++
>From mahboud@aggroup.com (Mahboud Zabetian)
Date: Sun, 13 Mar 1994 23:34:29 -0800
Organization: AG Group, Inc.
In article <2lr53n$lr3@amhux3.amherst.edu>, mbabramo@unix.amherst.edu
(MICHAEL BERNARD ABRAMOWICZ) wrote:
> > Well, you could use FlashMenuBar(), but I'm not sure whether it messes
> > with memory or not.
>
> This is exactly the solution. FlashMenuBar() does NOT move memory.
>
> > --
> > Terry Greeniaus tgreen@ersys.edmonton.ab.ca
> > Edmonton Remote Systems Serving Edmonton/Northern Alberta since 1982
>
> Michael Abramowicz
> Amherst College
> Writer, Inside Macintosh: Memory, More Macintosh Toolbox, Sound
I have tried to use FlashMenuBar in place of SysBeep. I don't find it as
useful as SysBeep though. It is very hard to miss a SysBeep, but
FlashMenuBar is easy to miss. Especially if you have a faster machine.
-mahboud
- -------------------------------------------------------------
Mahboud Zabetian
mahboud@aggroup.com
ag group, inc.
2540 camino diablo, suite 200
walnut creek, ca 94596
510-937-7900 voice
510-937-2479 fax
510-937-6704 ara
ftp.aggroup.com anonymous ftp
+++++++++++++++++++++++++++
>From Greg_Marriott@genmagic.com (Greg Marriott)
Date: Mon, 14 Mar 1994 01:55:17 -0800
Organization: General Magic, Inc.
mbabramo@unix.amherst.edu (MICHAEL BERNARD ABRAMOWICZ) wrote:
> > Well, you could use FlashMenuBar(), but I'm not sure whether it messes
> > with memory or not.
>
> This is exactly the solution. FlashMenuBar() does NOT move memory.
Wrong.
This took me less than a minute to check out. Among the calls made inside
FlashMenuBar(): NewHandle() and SetHandleSize().
--
Greg Marriott
Just Some Guy
General Magic, Inc.
Disclaimer: My opinions are not necessarily the same as General Magic's.
(can a company even HAVE an opinion?)
---------------------------
>From perlis_a@math.lsu.edu (Alexander Perlis)
Subject: Improving DrawText speed (Was: Color Terminal Emulator)
Date: 11 Mar 1994 18:28:27 GMT
Organization: Louisiana State University InterNetNews Site
In article <trygve-100394010606@kip-87.apple.com> trygve@apple.com (Trygve
Isaacson) writes:
>
> 2) Optimize out whitespace: move the pen instead of drawing blanks. Of
> course, this assumes you can calculate the character width ahead of
time,
> which assumes you're using a monospaced font. Note that boldface throws
a
> wrench in things unless your font's bold maintains the same character
width
> as plain, as does our Noiro font shipped with the SNA ps emulators.
>
> Trygve Isaacson
> SNA ps engineer
> Apple Computer, Inc.
I thought the built-in QuickDraw routines for drawing text simply ASSUME
that the space character (ASCII 32) in every font is truly a space and
simply move the pen without drawing anything when in srcOr mode. Of
course, if your font is monospaced and you have a bunch of spaces, it
might be faster to just skip over that than letting QuickDraw move the pen
a bunch of times, but I don't believe that the speedup is too significant
in the sense that one should worry more about speeding up the drawing of
actual text than speeding up the movement of the pen over empty regions.
If you put a graphic character in position 32 of a font, it will NOT be
displayed. As far as I can tell, this behavior, and a few other subleties
involving graphic characters in the control positions of a font,
characters 0 through 31, have never been fully documented or explained by
Apple. Please correct me if I'm wrong and point me in the direction of
such documentation.
I got around the problems in QuickDraw by writing a complete replacement
for the text drawing system (not too difficult since I only use monospaced
fonts in terminal emulation) which can handle fonts of 256 true graphic
characters. This solution proved faster than using two Macintosh fonts
with 128 characters each to simulate a 256-character font and swapping
between the two fonts all the time.
Incidentally, I never understood WHY QuickDraw has trouble drawing text in
srcCopy mode. The only slowdown should come when it has to draw a space,
since now it must actually erase the rectangle rather than simply moving
the pen. But that should not account for the major difference in speed
between srcOr and srcCopy. Can someone at Apple explain this?
Alexander Perlis
perlis_a@math.lsu.edu
---------------------------
>From atotic@void.ncsa.uiuc.edu (Alexsander Totic)
Subject: Interface guidelines for extra program files
Date: 16 Mar 94 16:36:40 GMT
Organization: University of Illinois at Urbana
I am building a program that creates and uses several external files besides
preferences. I have always disliked any external file approaches, but
this time I have to store data in this way. I was wandering what the
Apple's recommendation for storing of these files are: should application
have its own folder somewhere on a disk, or in a system folder, or spread
around through user preferences.
Allowing user to specify location of external folder allows multiple users
to start up an application by clicking on their preferences file, and have
everything work fine. But it also confuses them, especially when there are
many external files.
There is no right solution, so I would like to skip the responsibility, and
follow the guidelines.
Aleks
--
Aleksandar Totic -- MacMosaic developer -- atotic@ncsa.uiuc.edu
Software Development Group National Center for Supercomputing Applications
http://www.ncsa.uiuc.edu/SDG/People/atotic/alex.html
+++++++++++++++++++++++++++
>From pcastine@jake.prz.tu-berlin.de (Peter Castine)
Date: Thu, 17 Mar 1994 20:57:38 GMT
Organization: PRZ TU-Berlin
Alexsander Totic writes:
>I am building a program that creates and uses several external files besides
>preferences. I have always disliked any external file approaches, but
>this time I have to store data in this way. I was wandering what the
>Apple's recommendation for storing of these files are: should application
>have its own folder somewhere on a disk, or in a system folder, or spread
>around through user preferences.
>
>Allowing user to specify location of external folder allows multiple users
>to start up an application by clicking on their preferences file, and have
>everything work fine. But it also confuses them, especially when there are
>many external files.
>
>There is no right solution, so I would like to skip the responsibility, and
>follow the guidelines.
>
The only guideline is "Don't put user files in the same folder as
the application." This is because the application might well be on
a file server and the user would probably not have write access to
that folder.
I think the best solution is to do what QuickMail (and several other
programs) does: instead of a single file in the user's Preferences
folder, it creates a '<AppName> Stuff' folder in the Preferences
folder, and dumps everything in there.
Make sure to use the _FindFolder trap (if it's available) when looking
for the Prefs folder. It is *NOT* called 'Preferences' on many Macs.
--
Peter Castine | One child is shot every two hours
pcastine@jake.kgw.tu-berlin.de | in the U.S.A.
| Thank you for blocking gun control,
| N.R.A.
---------------------------
>From jafl@cco.caltech.edu (John Lindal)
Subject: Intermixing graphics and text
Date: 15 Mar 1994 01:35:47 GMT
Organization: California Institute of Technology, Pasadena
Has anyone written any straight code or TCL classes that allow pictures
and text to be intermixed? Of these, is there anyone willing to share this?
(or sell it for that matter?)
Thanks. John Lindal
+++++++++++++++++++++++++++
>From thunderone@delphi.com
Date: Tue, 15 Mar 94 02:40:05 -0500
Organization: Delphi (info@delphi.com email, 800-695-4005 voice)
John Lindal <jafl@cco.caltech.edu> writes:
>Has anyone written any straight code or TCL classes that allow pictures
>and text to be intermixed? Of these, is there anyone willing to share this?
>(or sell it for that matter?)
If you want to use TextEdit, it's pretty simple to do. Here's how I do
it. Note that pictHandle is an array containing PICT resources
(surprise!) and pictPositions is an array that holds the number of the
character that the lower left corner of the picture is anchored on.
Point tPoint;
PicHandle WhiteNoise;
short i;
Rect theRect;
/ GrafPtr old;
CGrafPtr theGraf=(CGrafPtr)theWindow;
SetPort(thePort);
if(numPicts){
for(i=1;i<=numPicts;i++){
WhiteNoise=pictHandle[i];
if(!WhiteNoise)
return;
tPoint=TEGetPoint(pictPositions[i],theTE);
HLockHi((Handle)WhiteNoise);
theRect=(**WhiteNoise).picFrame;
theRect.right=tPoint.h+(theRect.right-theRect.left);
theRect.top=tPoint.v-(theRect.bottom-theRect.top);
theRect.left=tPoint.h;
theRect.bottom=tPoint.v;
UQD::KillClip();
ClipRect(&teSquare);//(**theTE).viewRect
DrawPicture(WhiteNoise,&theRect);
if(pictPositions[i]>=(**theTE).selStart&&pictPositions[i]<(**theTE).
selEnd){
if(UQD::BitDepth()>1){
PenMode(adMin);
RGBForeColor(&(**(GVarHandle)theGraf->grafVars).rgbHiliteCol
or);
BackColor(blackColor);
PaintRect(&theRect);
}else{
InvertRect(&theRect);
}
}
ForeColor(blackColor);
BackColor(whiteColor);
UQD::RestoreClip();
HUnlock((Handle)WhiteNoise);
}
}
Chris
-
Chris Thomas, Delphi ICONtact Developer Database Librarian
thunderone@delphi.com
---------------------------
>From ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University)
Subject: Let's kill 24-bit mode! (was Re: Let's kill System 6!)
Date: 14 Mar 94 18:31:16 +1300
Organization: University of Waikato, Hamilton, New Zealand
OK, let's start a new version of this thread, shall we?
With more and more machines running with more than 8MB of RAM, is it worth
still testing your code to make sure it works in 24-bit mode? It's so much
easier leaving out all those StripAddress calls, rather than trying to remember
when you need them and when you don't, don't you think?
I've been running a home machine in 32-bit mode for close to 3 years now.
First it was an LC with 10MB, now it's a C650 with 16MB. And Godot, my long-
awaited, brand-spanking-new 840AV at work, couldn't run in 24-bit mode if I
wanted it to.
So what do other people think? Is it time to declare 24-bit mode dead yet...?
Lawrence D'Oliveiro fone: +64-7-856-2889
Info & Tech Services Division fax: +64-7-838-4066
University of Waikato electric mail: ldo@waikato.ac.nz
Hamilton, New Zealand 37^ 47' 26" S, 175^ 19' 7" E, GMT+13:00
+++++++++++++++++++++++++++
>From jwbaxter@olympus.net (John W. Baxter)
Date: Mon, 14 Mar 1994 09:18:43 -0800
Organization: Internet for the Olympic Peninsula
In article <1994Mar14.183116.26366@waikato.ac.nz>, ldo@waikato.ac.nz
(Lawrence D'Oliveiro, Waikato University) wrote:
> So what do other people think? Is it time to declare 24-bit mode dead yet...?
If you like, and test for the machine being in 24-bit mode at the start of
your code, and alert and exit gracefully. I don't mind being told gently
that your code won't work on my secondary machine (a 4 meg Mac Plus). I do
mind if it crashes. And I mind a WHOLE LOT if it corrupts the disk
while/before crashing, or (worse) corrupts the disk without crashing.
Same with my primary machine, in the once-every-6-months situation where I
set it to 24-bit mode for some odd reason.
With some of the newest machines not being able to run in 24-bit mode, the
time is approaching, but it may not be here yet.
--
John Baxter Port Ludlow, WA, USA [West shore, Puget Sound]
jwbaxter@pt.olympus.net
+++++++++++++++++++++++++++
>From u9119523@sys.uea.ac.uk (Graham Cox)
Date: Tue, 15 Mar 1994 17:41:52 GMT
Organization: School of Information Systems, UEA, Norwich
In article <1994Mar14.183116.26366@waikato.ac.nz>, ldo@waikato.ac.nz
(Lawrence D'Oliveiro, Waikato University) wrote:
> OK, let's start a new version of this thread, shall we?
>
> With more and more machines running with more than 8MB of RAM, is it worth
> still testing your code to make sure it works in 24-bit mode? It's so much
> easier leaving out all those StripAddress calls, rather than trying to remember
> when you need them and when you don't, don't you think?
>
> I've been running a home machine in 32-bit mode for close to 3 years now.
> First it was an LC with 10MB, now it's a C650 with 16MB. And Godot, my long-
> awaited, brand-spanking-new 840AV at work, couldn't run in 24-bit mode if I
> wanted it to.
>
> So what do other people think? Is it time to declare 24-bit mode dead yet...?
>
> Lawrence D'Oliveiro fone: +64-7-856-2889
> Info & Tech Services Division fax: +64-7-838-4066
> University of Waikato electric mail: ldo@waikato.ac.nz
> Hamilton, New Zealand 37^ 47' 26" S, 175^ 19' 7" E, GMT+13:00
Am I missing something vital here? I have never used StripAddress in any
program I've ever written and they all work in 24 or 32-bit mode. Either
what I'm doing is not very advanced compared to yours or you aren't doing
things the compatible way! I don't want to dump on you about this without
knowing the facts- I therefore assume the former (?). I believe that
addresses/pointers are always valid in whatever mode and OF COURSE you
never try to set the high byte of a handle right?
- ------------------------------------------------------------------------
Love & BSWK, Graham
-Everyone is entitled to their opinion, no matter how wrong they may be...
- ------------------------------------------------------------------------
+++++++++++++++++++++++++++
>From t-gaul@i-link.com (Troy Gaul)
Date: Tue, 15 Mar 1994 17:10:35 -0600
Organization: I-Link, Ltd.
In article <u9119523-150394174152@case6.sys.uea.ac.uk>,
u9119523@sys.uea.ac.uk (Graham Cox) wrote:
> In article <1994Mar14.183116.26366@waikato.ac.nz>, ldo@waikato.ac.nz
> (Lawrence D'Oliveiro, Waikato University) wrote:
>
> > OK, let's start a new version of this thread, shall we?
> >
> > With more and more machines running with more than 8MB of RAM, is it worth
> > still testing your code to make sure it works in 24-bit mode? It's so much
> > easier leaving out all those StripAddress calls, rather than trying to remember
> > when you need them and when you don't, don't you think?
> >
> > I've been running a home machine in 32-bit mode for close to 3 years now.
> > First it was an LC with 10MB, now it's a C650 with 16MB. And Godot, my long-
> > awaited, brand-spanking-new 840AV at work, couldn't run in 24-bit mode if I
> > wanted it to.
> >
> > So what do other people think? Is it time to declare 24-bit mode dead yet...?
>
> Am I missing something vital here? I have never used StripAddress in any
> program I've ever written and they all work in 24 or 32-bit mode. Either
> what I'm doing is not very advanced compared to yours or you aren't doing
> things the compatible way! I don't want to dump on you about this without
> knowing the facts- I therefore assume the former (?). I believe that
> addresses/pointers are always valid in whatever mode and OF COURSE you
> never try to set the high byte of a handle right?
There are cases where you must call StripAddress for a program to function
correctly in all 'modes'. It is possible that you haven't run across them.
One case in point is when you are manually switching the processor's
addressing modes (like, when working with directly accessing data in a
GWorld PixMap). Since the PixMap may be stored on a NuBus board's memory
(our of 24-bit range), you should switch to 32-bit mode to access the data
(and back when you're done). If you have a pointer in a local variable
from before you switched out of 24-bit, it is possible this pointer has
some high bits being used, so you should strip it if you intend to
dereference it from 32-bit mode.
Moral is: when you might be changing modes, you should be careful.
Or something like that. :)
_troy
//////// //////___Troy Gaul_________________________t-gaul@i-link.com__ //
// // I-Link, Ltd. ; West Des Moines, Iowa //
// // // "Iungo ergo sum." (I-Link, therefore I am.) //
// //////________________________________________________________ //
>From DACRXL01.OURX124@tcp30.dx.deere.com (Juan Ingles)
Subject: Let's kill 24-bit mode! (was Re: Let's kill System 6!)
Date: Tue, 15 Mar 1994 23:47:30 GMT
Organization: Proteus Ventures, Inc.
In article <1994Mar14.183116.26366@waikato.ac.nz>
ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University) writes:
> With more and more machines running with more than 8MB of RAM, is it worth
> still testing your code to make sure it works in 24-bit mode? It's so much
> easier leaving out all those StripAddress calls, rather than trying to remember
> when you need them and when you don't, don't you think?
Huh? StripAddress? What's that? :-) :-)
Juan Ingles
<DACRXL01.OURX124@tcp30.dx.deere.com>
--
Proteus Ventures, Inc. - Computer Software Consulting and Development
1514 Oriole Ave * Waterloo, IA 50701 * (319) 232-0985
+++++++++++++++++++++++++++
>From sw@network-analysis-ltd.co.uk (Sak Wathanasin)
Date: Wed, 16 Mar 94 00:15:54 GMT
Organization: Network Analysis Ltd
In article <u9119523-150394174152@case6.sys.uea.ac.uk> (comp.sys.mac.programmer), u9119523@sys.uea.ac.uk (Graham Cox) writes:
> ... I believe that
> addresses/pointers are always valid in whatever mode and OF COURSE you
> never try to set the high byte of a handle right?
You don't have to: the resource manager will happily set them for you,
for example. Most of the time it doesn't matter, but there are times
when it does (like when you call a code resource loaded with the RM and
the CR turns on 32-bit mode - your return addreses on the stack become
instant garbage). There's a tech note that tells you when StripAdress
is necessary; can't remember what it's called off the top of my head.
Sak Wathanasin
Network Analysis Limited
178 Wainbody Ave South, Coventry CV3 6BX, UK
Internet: sw@network-analysis-ltd.co.uk
uucp: ...!uknet!nan!sw AppleLink: NAN.LTD
Phone: (+44) 203 419996 Mobile:(+44) 850 587411 Fax: (+44) 203 690690
---------------------------
>From bsc@oui.com (Bill Stewart-Cole)
Subject: Let's kill system 6!
Date: 20 Feb 1994 13:12:15 -0600
Organization: Odyssey Ultraware Inc
St Louis, MO
The whole discussion on supporting system 6 has spurred some thoughts:
Would not Mac developers benefit by a 100% move to system 7?
Would not Mac users benefit by upgrading to 7 and Macs that can run it well?
It is a royal pain to support BOTH the full features of 7, and system 6. I
have taken 2 tracks: 1. if the program specifically calls for features of 7,
I check for it and politely quit if I don't have it. 2. If the program can be
used just fine without 7-specific features, I use all the system 6 versions
and let the program crash on the rare 512k (not 512ke) running 4.1. The one
time I tried to develop a program for an either/or operation, the result was
a confusing program to debug and a program far too big. And a nervous tic:).
We'd all make smaller, clearer, and less bug-prone code if we stuck to one
set of system features. Programs would get out faster. Money would flow in
for programs sooner. We'd have fewer ulcers.
On the user side, it's important to consider who is still using system 6 and
why. They are essentially 2 types: 1. People who have a fixed function for
their Mac that works well and can be done with 6. 2. People who would do
better running 7 on a faster Mac. In the first group, they aren't buying
software. In the second, they are ready to move to 7 with the slightest
nudge. A //ci-class Mac is a fine platform for 7, and the 5 machines in that
general performance range are breaking below $700 on the used market. Even
if Joe Plus User won't bite on a $2000 PDM PowerMac, he is not unlikely to
see the used //ci's and //cx's and LC3's being dumped to upgrade by other
users who want faster boxes as tempting. The increased pressure in that
direction of 7-only software (i.e. requiring a good machine for running 7)
will make for a user base with more compatibility, more power, and less
ghettoizing of users.
Anyway, I think it is a positive step for developers to move away from
supporting system 6 because of the good it will do to get everyone running 7,
both for developers and for users.
+++++++++++++++++++++++++++
>From rrwood@r-node.io.org (Roy Wood)
Date: 21 Feb 1994 10:41:47 -0500
Organization: Internex Online (io.org) Data: 416-363-3783 Voice: 416-363-8676
Another group of users stuck with sloooooooow system 6 machines are students
and teachers at public schools. I'd love to upgrade our lab to faster
machines, but there's no way our budget can afford it.
This is not such a huge problem, in terms of the thread being discussed,
since we're doing mostly word processing and other mundane things, and
we're hardly likely to rush out and invest in any bleeding-edge killer
apps anyway.
-Roy
+++++++++++++++++++++++++++
>From time@garnet.msen.com (Tim Endres)
Date: 22 Feb 1994 17:32:28 GMT
Organization: Msen, Inc. -- Ann Arbor, MI (account info: +1 313 998-4562)
Bill Stewart-Cole (bsc@oui.com) wrote:
: The whole discussion on supporting system 6 has spurred some thoughts:
: Would not Mac developers benefit by a 100% move to system 7?
: Would not Mac users benefit by upgrading to 7 and Macs that can run it well?
This is a marketing decision, not a engineering decision.
Perform your own market analysis and make a business decision.
That is what most developers do...
+++++++++++++++++++++++++++
>From wbostow@hounix.org (Wayne Bostow)
Date: Thu, 24 Feb 1994 15:09:52 GMT
Organization: Houston UNIX Users Group (HOUNIX), Houston, TX
: Would not Mac developers benefit by a 100% move to system 7?
Well, not me! I am ticked at Apple for allowing no upgrade path from
MPW 1.0. I bought everything in '87 for under $300. I did not get several
upgrades because APPLE said not to unless you had a machine to handle
it. My current version will not even launch under sys 7. To get everything
now is about $1000 plus a new hard drive and more memory.
As an assembly programmer, I see most of the improvements as clutter.
--
__________________________________________________________
Wayne Bostow "The HangulMan"
10558 Alcott, Houston, TX 77043 ph. (713)468-6546
wbostow@hounix.org
+++++++++++++++++++++++++++
>From ingemar@lysator.liu.se (Ingemar Ragnemalm)
Date: Fri, 25 Feb 1994 11:04:37 GMT
Organization: (none)
time@garnet.msen.com (Tim Endres) writes:
>Bill Stewart-Cole (bsc@oui.com) wrote:
>: The whole discussion on supporting system 6 has spurred some thoughts:
>: Would not Mac developers benefit by a 100% move to system 7?
>: Would not Mac users benefit by upgrading to 7 and Macs that can run it well?
That means killing off all Macs below LC III. Plus, SE, LC, LC II, Classic,
Classic II, Color Classic, PB100,Portable, perhaps even IIcx, IIsi and IIvi.
All those Macs are significantly nicer with System 6. Apple has designed
System 7 in a way that makes a 100% move to System 7 *impossible*. System
6 won't go away until the last of the above Macs stop working. Sure, many
users will move to sys 7 even with slow Macs, usually since they are forced
to, but lots of them will run system 6 until they die.
And they won't die for a long time yet. You might be able to get rid of
some by good trade-in offers, but even that won't help. Would you trade an
SE for a LC475 at half the price? Sure? Many people will say yes, but some
may think twice. Some of those Macs - especially SE - are *much* more
reliable than the new ones. That's (one of the reasons) why they were
so expensive.
>This is a marketing decision, not a engineering decision.
>Perform your own market analysis and make a business decision.
>That is what most developers do...
Isn't this both marketing and engineering?
--
- -
Ingemar Ragnemalm, PhD
Image processing, Mac shareware games
E-mail address: ingemar@isy.liu.se or ingemar@lysator.liu.se
+++++++++++++++++++++++++++
>From j-norstad@nwu.edu (John Norstad)
Date: Fri, 25 Feb 1994 13:28:09 -0600
Organization: Northwestern University
In article <CLs1Fr.Fup@lysator.liu.se>, ingemar@lysator.liu.se (Ingemar
Ragnemalm) wrote:
> That means killing off all Macs below LC III. Plus, SE, LC, LC II, Classic,
> Classic II, Color Classic, PB100,Portable, perhaps even IIcx, IIsi and IIvi.
> All those Macs are significantly nicer with System 6.
I couldn't disagree more strongly. I have a Mac Classic at home with 4
megs. It is *infinitely* nicer with System 7 than with System 6. My two
kids, ages 8 and 13, who use it for homework, agree with me 100%.
You need a Mac Plus or later with at least 4 megs to run System 7. It
works just fine on the old Macs, and is nicer than System 6 on those Macs
for exactly the same reason that it's nicer than System 6 on the newer and
bigger Macs.
At NU, we have completely dropped support for System 6. We tell people to
get at least 4 megs and run System 7 on their old Macs. They can stay with
System 6 if they wish, but if they do they are on their own, with no
support from us. This was a good decision, IMHO.
--
John Norstad
Academic Computing and Network Services
Northwestern University
j-norstad@nwu.edu
+++++++++++++++++++++++++++
>From DACRXL01.OURX124@tcp30.dx.deere.com (Juan Ingles)
Date: Fri, 25 Feb 1994 19:31:46 GMT
Organization: Proteus Ventures, Inc.
In article <CLs1Fr.Fup@lysator.liu.se>
ingemar@lysator.liu.se (Ingemar Ragnemalm) writes:
> Some of those Macs - especially SE - are *much* more
> reliable than the new ones. That's (one of the reasons) why they were
> so expensive.
Huh? Is there any evidence to support this? In my personal dealings, I
have found newer machines more reliable.
>That's (one of the reasons) why they were so expensive.
If that were true, they would still hold a high value. I would think
that profit margins, R&D, and inflation make up 99% of the reason.
Juan Ingles
<DACRXL01.OURX124@tcp30.dx.deere.com>
--
Proteus Ventures, Inc. - Computer Software Consulting and Development
1514 Oriole Ave * Waterloo, IA 50701 * (319) 232-0985
--
All reality portrayed in this message is fictional. Any resemblance to
any real reality, alive or dead, is purely coincidental and
unintentional.
+++++++++++++++++++++++++++
>From d88-jwa@mumrik.nada.kth.se (Jon Wdtte)
Date: 25 Feb 1994 22:08:30 GMT
Organization: Royal Institute of Technology, Stockholm, Sweden
In <CLs1Fr.Fup@lysator.liu.se> ingemar@lysator.liu.se (Ingemar Ragnemalm) writes:
>That means killing off all Macs below LC III. Plus, SE, LC, LC II, Classic,
>Classic II, Color Classic, PB100,Portable, perhaps even IIcx, IIsi and IIvi.
My value judgement is that all of the color-capable Macs are
also System-7-capable.
>All those Macs are significantly nicer with System 6. Apple has designed
>System 7 in a way that makes a 100% move to System 7 *impossible*. System
"All those Macs"
Apple is increasing its market share som 30% a year, and all macs sold
the last few years have been System 7 Macs. System 6 will go away, not
only because people upgrade, but because Apple sells so many more macs
a year now than in 1991.
Cheers,
/ h+
--
-- Jon W{tte, h+@nada.kth.se, Mac Hacker Deluxe --
This article printed on 100% recycled electrons.
+++++++++++++++++++++++++++
>From cabu1hj@ube.ub.umd.edu
Date: 26 Feb 94 22:52:01 -0500
Organization: University of Baltimore
In article <CLs1Fr.Fup@lysator.liu.se>, ingemar@lysator.liu.se
(Ingemar Ragnemalm) writes:
>
> [stuff deleted]
>
> That means killing off all Macs below LC III. Plus, SE, LC, LC II, Classic,
> Classic II, Color Classic, PB100,Portable, perhaps even IIcx, IIsi and IIvi.
> All those Macs are significantly nicer with System 6.
I think you need to double check statements like this. Several of these
systems run just fine with System 7.0, 7.0.1, & 7.1. Not with the
factory shipped memory (like 3MB on the IIsi). Running them with
8MB+ isn't unrealistic given the size of current applications either.
+++++++++++++++++++++++++++
>From qsi@NU91.wlink.nl (Peter Kocourek)
Date: Sun, 27 Feb 1994 00:22:45 +0100
Organization: (none)
Ingemar Ragnemalm wrote in a message on 25 Feb 94
IR> That means killing off all Macs below LC III. Plus, SE, LC,
IR> LC II, Classic, Classic II, Color Classic, PB100,Portable,
IR> perhaps even IIcx, IIsi and IIvi. All those Macs are significantly
IR> nicer with System 6. Apple has designed System 7 in a way that
I beg to differ. I have a IIsi here, and I don't see how running System 6 on it
would make it "nicer". I'd lose aliases, drag & drop, AppleEvents (and hence
AppleScript), a much better Finder, WorldScript, and Publish & Subscribe. How
can the loss of these make the machine "nicer"?
IR> makes a 100% move to System 7 *impossible*. System 6 won't
IR> go away until the last of the above Macs stop working. Sure,
IR> many users will move to sys 7 even with slow Macs, usually
IR> since they are forced to, but lots of them will run system
IR> 6 until they die.
Oh, sure, a 100% adoption rate for System 7 won't ever happen; after all, there
are still people running CP/M too. :-) But I think you are wrong with your
classification of System 6 Macs; I don't know anybody running System 6 on an LC
or Mac II. And System 6 is dying very quickly, now that Apple is selling huge
amounts of Macs every year (perhaps as many as 4 million this year), none of
which can run System 6.
IR> And they won't die for a long time yet. You might be able to
IR> get rid of some by good trade-in offers, but even that won't
IR> help. Would you trade an SE for a LC475 at half the price?
IR> Sure? Many people will say yes, but some may think twice. Some
IR> of those Macs - especially SE - are *much* more reliable than
IR> the new ones. That's (one of the reasons) why they were so
IR> expensive.
I'm extremely skeptical about this claim. Could you provide some evidence to
support this? The reason they were so expensive was because Apple had huge
profit margins.
YHS:QSI!
+++++++++++++++++++++++++++
>From isis@netcom.com (Mike Cohen)
Date: Sun, 27 Feb 1994 20:27:17 GMT
Organization: ISIS International
cabu1hj@ube.ub.umd.edu writes:
>In article <CLs1Fr.Fup@lysator.liu.se>, ingemar@lysator.liu.se
>(Ingemar Ragnemalm) writes:
>>
>> [stuff deleted]
>>
>> That means killing off all Macs below LC III. Plus, SE, LC, LC II, Classic,
>> Classic II, Color Classic, PB100,Portable, perhaps even IIcx, IIsi and IIvi.
>> All those Macs are significantly nicer with System 6.
>I think you need to double check statements like this. Several of these
>systems run just fine with System 7.0, 7.0.1, & 7.1. Not with the
>factory shipped memory (like 3MB on the IIsi). Running them with
>8MB+ isn't unrealistic given the size of current applications either.
I have a PB100, IIsi (with 14 megs of RAM & a FPU) and an SE/30 (acting as a
file server). All of them run System 7 or later (S7Pro on the IIsi) and I
don't think I could live with anything less. System 6 should finally be laid
to rest. The speed & size difference isn't that great (the lean system on my
PB even though I have CPU, FaxPro, & ARA is only 1300K) and the many benefits
& convenience features of System 7 far outweigh the tiny speed difference.
--
Mike Cohen - isis@netcom.com
NewtonMail: MikeC49506 / ALink: D6734 / AOL: MikeC20
+++++++++++++++++++++++++++
>From L.H.Wood@lut.ac.uk
Date: Sun, 27 Feb 1994 22:56:15 GMT
Organization: Loughborough University, UK.
In article <762314409.AA03366@nu91.wlink.nl> qsi@NU91.wlink.nl (Peter Kocourek) writes:
>Ingemar Ragnemalm wrote in a message on 25 Feb 94
>
> IR> That means killing off all Macs below LC III. Plus, SE, LC,
> IR> LC II, Classic, Classic II, Color Classic, PB100,Portable,
> IR> perhaps even IIcx, IIsi and IIvi. All those Macs are significantly
> IR> nicer with System 6. Apple has designed System 7 in a way that
>
>I beg to differ. I have a IIsi here, and I don't see how running System 6 on it
>would make it "nicer". I'd lose aliases, drag & drop, AppleEvents (and hence
>AppleScript), a much better Finder, WorldScript, and Publish & Subscribe. How
>can the loss of these make the machine "nicer"?
>
System 6 and 7 store things at the opposite ends of memory to each other.
Under S6 on a IIsi, a large disk cache is not required to boost drawing-to
video speeds. Nothing gets put in the remaining part of that megabyte until
you fill the machine right up.
Considering that the disk cache in not used under S6 Multifinder, this is
a blessing twice over. (Aside: I've read that Apple are redoing the disk-cache
code. Can we expect a disk cache whose size you don't set, that utilises free
memory wherever it can, a la Windows NT, for System 7.5?)
L.
+++++++++++++++++++++++++++
>From neeri@iis.ee.ethz.ch (Matthias Neeracher)
Date: 28 Feb 94 17:26:34
Organization: Integrated Systems Laboratory, ETH, Zurich
In article <CLs1Fr.Fup@lysator.liu.se>, ingemar@lysator.liu.se (Ingemar Ragnemalm) writes:
> time@garnet.msen.com (Tim Endres) writes:
>>Bill Stewart-Cole (bsc@oui.com) wrote:
>>: The whole discussion on supporting system 6 has spurred some thoughts:
>>: Would not Mac developers benefit by a 100% move to system 7?
>>: Would not Mac users benefit by upgrading to 7 and Macs that can run it well?
> That means killing off all Macs below LC III. Plus, SE, LC, LC II, Classic,
> Classic II, Color Classic, PB100,Portable, perhaps even IIcx, IIsi and IIvi.
> All those Macs are significantly nicer with System 6.
I do most of my programming on an original Mac II. For about a year, I had one
System 6 and one System 7 startup volume, but it turned out taht I never used
the System 6 volume anymore.
Matthias
- ---
Matthias Neeracher neeri@iis.ee.ethz.ch
"I feel morally and intellectually obligated simply to concede that the
death penalty experiment has failed."
-- Supreme Court Justice Harry A. Blackmun
+++++++++++++++++++++++++++
>From wbostow@hounix.org (Wayne Bostow)
Date: Mon, 28 Feb 1994 21:39:45 GMT
Organization: Houston UNIX Users Group (HOUNIX), Houston, TX
>If that were true, they would still hold a high value. I would think
that profit margins, R&D, and inflation make up 99% of the reason.
I think the used price lists show SE30s higher that Classic IIs and
IIcx's higher than their LC replacements. I attribute it to people who
want to continue using 6.
There are lots of us not ready to spend thousands on hardware and
software upgrades even to get something " *infinitely* nicer".
--
__________________________________________________________
Wayne Bostow "The HangulMan"
10558 Alcott, Houston, TX 77043 ph. (713)468-6546
wbostow@hounix.org
+++++++++++++++++++++++++++
>From gdl@stlawrence.maths (Mr_G._Landweber_student_tel_2-73550)
Date: 28 Feb 1994 23:48:12 GMT
Organization: (none)
In article <CLs1Fr.Fup@lysator.liu.se>
ingemar@lysator.liu.se (Ingemar Ragnemalm) writes:
> Some of those Macs - especially SE - are *much* more
> reliable than the new ones. That's (one of the reasons) why they were
> so expensive.
I remember writing a 3-page essay with WriteNow on my old Mac SE, and
it crashed at least three times. More recently, I wrote a 50+ page
thesis with Word and it only crashed once.
In my experience, my Mac IIcx/Rocket is much more stable than my SE
ever was. In fact, most of my crashes come from bugs in pre-release
versions of Greg's Buttons (some pretty spectatular things happen when
you patch _GetResource and trash A1).
-- Greg "Buttons" Landweber
gdl@maths.ox.ac.uk
+++++++++++++++++++++++++++
>From cabu1hj@ube.ub.umd.edu
Date: 28 Feb 94 19:53:09 -0500
Organization: University of Baltimore
In article <WISEKB.12.0016AE3C@caedm.et.byu.edu>,
WISEKB@caedm.et.byu.edu (Kevin B. Wise) writes:
>
> Long live system 6!!!!!!!!!
Spoken like a ture horse & buggy man.
+++++++++++++++++++++++++++
>From jwbaxter@olympus.net (John W. Baxter)
Date: Tue, 01 Mar 1994 08:48:30 -0800
Organization: Internet for the Olympic Peninsula
I don't want to prevent anyone from using System 6 who wants to do so.
On the other hand, I haven't written anything for System 6 for a couple of
years. I've forgotten how. I don't want to relearn. So...what I write
won't do any good for people who run System 6. [But...I haven't released
anything major recently, anyhow.]
For some developers, there's still a nice market of System 6 users. Go for
it!
--
John Baxter Port Ludlow, WA, USA [West shore, Puget Sound]
jwbaxter@pt.olympus.net
+++++++++++++++++++++++++++
>From d88-jwa@mumrik.nada.kth.se (Jon Wdtte)
Date: 1 Mar 1994 19:42:48 GMT
Organization: Royal Institute of Technology, Stockholm, Sweden
In <1994Feb28.213945.20363@hounix.org> wbostow@hounix.org (Wayne Bostow) writes:
> I think the used price lists show SE30s higher that Classic IIs and
>IIcx's higher than their LC replacements. I attribute it to people who
>want to continue using 6.
I attribute it to an informed market; the SE30 is twice the speed
of the Classic II and can take more memory; the IIcx is not only twice
the speed of the LC, it also has three NuBus slots.
Cheers,
/ h+
--
-- Jon W{tte, h+@nada.kth.se, Mac Hacker Deluxe --
"Don't use the Layer Manager"
+++++++++++++++++++++++++++
>From temple@itd.nrl.navy.mil (Dr. Jon Gerard Temple)
Date: Wed, 2 Mar 1994 20:11:17 GMT
Organization: Naval Research Laboratory
In article <2l05ro$mqi@news.kth.se>
d88-jwa@mumrik.nada.kth.se (Jon Wdtte) writes:
> In <1994Feb28.213945.20363@hounix.org> wbostow@hounix.org (Wayne Bostow) writes:
>
> > I think the used price lists show SE30s higher that Classic IIs and
> >IIcx's higher than their LC replacements. I attribute it to people who
> >want to continue using 6.
>
> I attribute it to an informed market; the SE30 is twice the speed
> of the Classic II and can take more memory; the IIcx is not only twice
> the speed of the LC, it also has three NuBus slots.
>
Agreed. Moreover, the SE/30 and IIcx were quality machines. Designed
well and made to last. The LCs and Classic IIs always feel cheap in
comparison, with much less care taken in their design and manufacture.
Not that I would turn my nose up at a LC475 (Q605)...
Jon
+++++++++++++++++++++++++++
>From ingemar@lysator.liu.se (Ingemar Ragnemalm)
Date: Wed, 2 Mar 1994 19:29:08 GMT
Organization: (none)
cabu1hj@ube.ub.umd.edu writes:
>In article <CLs1Fr.Fup@lysator.liu.se>, ingemar@lysator.liu.se
>(Ingemar Ragnemalm) writes:
>>
>> [stuff deleted]
>>
>> That means killing off all Macs below LC III. Plus, SE, LC, LC II, Classic,
>> Classic II, Color Classic, PB100,Portable, perhaps even IIcx, IIsi and IIvi.
>> All those Macs are significantly nicer with System 6.
>I think you need to double check statements like this. Several of these
>systems run just fine with System 7.0, 7.0.1, & 7.1. Not with the
>factory shipped memory (like 3MB on the IIsi). Running them with
>8MB+ isn't unrealistic given the size of current applications either.
I didn't say it won't work - it will, at least with 4 megs. I said that
those Macs are so slow that they are *noticeably* more sluggish (at least
in the Finder) when using System 7, and therefore many users won't change.
And as long as many users have a better life with the *old* system, it
won't go away in a long time.
I've tried Sys 7 on my SE. Never again. I use System 7 on my LC. I wish
I didn't have to, but with sys 6 it can't print due to the sys 7-running
IIfx that uses the same printer. When I switch the LC to sys 6 (I have both
on it, on separate disks) it feels like if I had plugged in an accelerator
board.
Plusses, SE's and Classics are best used with sys 6, if at all possible
(again, sharing a printer might make it impossible). Faster, more memory
(max 4, you know). LC's only for the speed difference. At IIsi, it's
getting fast enough to consider upgrading to 7, but it does slow down...
About that printer problem... Anyone who knows a way to make a sys 6 Mac
work with the new printer drivers? Will 6.0.8 fix it? (Dumping in the
new drivers didn't.)
--
- -
Ingemar Ragnemalm, PhD
Image processing, Mac shareware games
E-mail address: ingemar@isy.liu.se or ingemar@lysator.liu.se
+++++++++++++++++++++++++++
>From ingemar@lysator.liu.se (Ingemar Ragnemalm)
Date: Wed, 2 Mar 1994 19:41:30 GMT
Organization: (none)
L.H.Wood@lut.ac.uk writes:
>Aside: I've read that Apple are redoing the disk-cache
>code. Can we expect a disk cache whose size you don't set, that utilises free
>memory wherever it can, a la Windows NT, for System 7.5?
That could be nice, but even more important: will Apple get it act together
and fix the memory management overall? It seems like RamDoubler will fix
most of it for now, but fixes like that should go into the OS. Memory
protection would be nice too. (I suppose I won't get that from RamDoubler.)
--
- -
Ingemar Ragnemalm, PhD
Image processing, Mac shareware games
E-mail address: ingemar@isy.liu.se or ingemar@lysator.liu.se
+++++++++++++++++++++++++++
>From watkeyeh@dunx1.ocs.drexel.edu (Edwin H. Watkeys III)
Date: Thu, 3 Mar 1994 00:47:57 GMT
Organization: Drexel University
In article <CM1y4M.E9t@lysator.liu.se> ingemar@lysator.liu.se (Ingemar Ragnemalm) writes:
>[A lot of stuff deleted]
There's no point in arguing -- the speed tradeoff is worth it to me. I'd
sooner use a typewriter than System 6.
>
>About that printer problem... Anyone who knows a way to make a sys 6 Mac
>work with the new printer drivers? Will 6.0.8 fix it? (Dumping in the
>new drivers didn't.)
>
I thought this was the reason 6.0.8 came out in the first place (to make
System 6 compatible with System 7.x printing drivers). Try it.
Ed
--
Ed Watkeys watkeyeh@dunx1.ocs.drexel.edu Drexel University
Philosopher-Programmer EdWatkeys@distant.com Distant Software
+++++++++++++++++++++++++++
>From Brad Koehn <koehn@macc.wisc.edu>
Date: 4 Mar 1994 01:17:08 GMT
Organization: University of Wisconsin
In article <CM1y4M.E9t@lysator.liu.se> Ingemar Ragnemalm,
ingemar@lysator.liu.se writes:
>I didn't say it won't work - it will, at least with 4 megs. I said that
>those Macs are so slow that they are *noticeably* more sluggish (at least
>in the Finder) when using System 7, and therefore many users won't
change.
>And as long as many users have a better life with the *old* system, it
>won't go away in a long time.
>
>I've tried Sys 7 on my SE. Never again. I use System 7 on my LC. I wish
>I didn't have to, but with sys 6 it can't print due to the sys 7-running
>IIfx that uses the same printer. When I switch the LC to sys 6 (I have
both
>on it, on separate disks) it feels like if I had plugged in an
accelerator
>board.
>
>Plusses, SE's and Classics are best used with sys 6, if at all possible
>(again, sharing a printer might make it impossible). Faster, more memory
>(max 4, you know). LC's only for the speed difference. At IIsi, it's
>getting fast enough to consider upgrading to 7, but it does slow down...
>
>About that printer problem... Anyone who knows a way to make a sys 6 Mac
>work with the new printer drivers? Will 6.0.8 fix it? (Dumping in the
>new drivers didn't.)
The printer problem is from using the System 7 LW Driver alongside the
System 6 LW Driver. Just put the Sys6 driver on the Sys7 machine and the
printer won't re-initialize every time you print from the other machine.
Also, I agree that Sys7 is more sluggish than Sys6, but you have to take
into effect things like aliases (so you don't have to navigate to every
file) and AppleScript. System 7 lets the Finder do more, and if you take
advantage of the extra goodies, you can be more productive.
As someone (I believe it was Jon) pointed out, there are far more Sys7
Macs out there, and more and more software is Sys7 only. While there may
be some people out there that stick with Sys6, their number is getting
smaller every day. Also, Sys6 don't tend to buy lots of new software,
which is understandable, but doesn't help the "Sys7 required" trend.
_________________________________________________________________________
Brad Koehn Data Transformations, Inc. koehn@macc.wisc.edu
+++++++++++++++++++++++++++
>From worley@el.wpafb.af.mil (Rick Worley)
Date: Fri, 4 Mar 94 16:42:31 GMT
Organization: WL/ELM
>
>About that printer problem... Anyone who knows a way to make a sys 6 Mac
>work with the new printer drivers? Will 6.0.8 fix it? (Dumping in the
>new drivers didn't.)
>
6.0.8 is available from ftp.apple.com//dts/sys.soft
6.0.8 is compatible with System 7 laserwriter drivers
But you should install LaserWriter 8.1.1 on all your macs, it works with
both System 6 and 7.
Rick Worley Tel: (513) 255-7665
WL/ELM BLDG 620 Fax: (513) 476-4807
2241 AVIONICS CIRCLE SUITE 25 worley@el.wpafb.af.mil
WRIGHT-PATTERSON AFB OH 45433-7327
+++++++++++++++++++++++++++
>From wbostow@hounix.org (Wayne Bostow)
Date: Sun, 06 Mar 1994 23:02:22 GMT
Organization: Houston UNIX Users Group (HOUNIX), Houston, TX
>But you should install LaserWriter 8.1.1 on all your macs, it works with
both System 6 and 7.
Depends what you mean by "works".
I heard this nonsense when sys 7 first came out and wasted a lot
of time with it before taking it off to use with my LaserWriterPlus.
Thing is, with that printer, there is a max of about 128k free for
fonts using the sys 6 driver. Eat that away with the newer drivers
and you cannot print your existing documents.
If you are working alone and are printing OK now, don't change.
--
__________________________________________________________
Wayne Bostow "The HangulMan"
10558 Alcott, Houston, TX 77043 ph. (713)468-6546
wbostow@hounix.org
---------------------------
>From pope@imv.aau.dk (Povl H. Pedersen)
Subject: Never beep when using GWorlds. System software bug!
Date: 6 Mar 1994 12:52:05 GMT
Organization: Information and Media Science, Aarhus University, DENMARK
I just had to help a guy who used my PICT file saving code.
He had some problems, and had inserted a SysBeep() in the bottleneck
procedure to write the bytes.
Now, the way my routine works is to create a new GWorld, SetGWorld,
OpenPicture, CopyBits, ClosePicture.
The problem is, that the machine he uses has the volume set to 0.
When my GWorld is set, and the SysBeep() tries to flash the menubar,
then the machine crashes each and every time! When I replaced the
the SetGWorld with a SetPort to the port of the FronWindow(), then I
got the flashing menu bar. Setting the sound volume > 0 gave me the
beeps instead.
So I would appreciate if some dude at Apple could look the code over,
and make sure that FlashMenuBar() is only called with a valid GWorld,
or sets/restores the window Gworld itself.
Now, this problem will probably get low priority, as it affects <10% of
the Maacintosh users (those with sound level set to 0).
- -
Povl H. Pedersen - Macintosh Consultant and Programmer
System Administrator at the Aarhus Engineering School
pope@imv.aau.dk (preferred) / povlphp@uts.uni-c.dk
"Macintosh...for those who can see through Windows!"
+++++++++++++++++++++++++++
>From tgreen@ersys.edmonton.ab.ca (Terry Greeniaus)
Date: Thu, 10 Mar 94 15:46:30 MST
Organization: Edmonton Remote Systems #1
pope@imv.aau.dk (Povl H. Pedersen) writes:
> I just had to help a guy who used my PICT file saving code.
> He had some problems, and had inserted a SysBeep() in the bottleneck
> procedure to write the bytes.
>
> Now, the way my routine works is to create a new GWorld, SetGWorld,
> OpenPicture, CopyBits, ClosePicture.
>
> The problem is, that the machine he uses has the volume set to 0.
> When my GWorld is set, and the SysBeep() tries to flash the menubar,
> then the machine crashes each and every time! When I replaced the
> the SetGWorld with a SetPort to the port of the FronWindow(), then I
> got the flashing menu bar. Setting the sound volume > 0 gave me the
> beeps instead.
>
> So I would appreciate if some dude at Apple could look the code over,
> and make sure that FlashMenuBar() is only called with a valid GWorld,
> or sets/restores the window Gworld itself.
>
> Now, this problem will probably get low priority, as it affects <10% of
> the Maacintosh users (those with sound level set to 0).
>
Well, I have also had problems with GWorlds, (offscreen ports, actually,
but it's on a related topice.). If you are set to a port somewhere
offscreen, and call SetWTitle() it will try to draw the window into your
port off screen, and make funny things appear. (I'm not sure if the
Inside Mac description says the set the port to the window who's title
you're going to change, but that solved the problem.)
"Yes, I have tricks in my pocket, I have things up my sleeve. But I am
the opposite of a stage magician. He gives you illusion that has the
appearance of truth. I give you truth in the pleasant disguise of
illusion."
--Tom Wingfield
from "The Glass Menagerie" by T. Williams
+++++++++++++++++++++++++++
>From markhanrek@aol.com (MarkHanrek)
Date: 12 Mar 1994 04:37:00 -0500
Organization: America Online, Inc. (1-800-827-6364)
I could be wrong, but I believe your problems has to do with the graphic device
involved.
It is a common "programming error" to not restore the graphic device along with
the GWorld when working with GWorlds. This often happens when mixing the use of
GetPort/SetPort and GetGWorld/SetGWorld calls.
The guy who was having the problems using sysbeep was doing something
incorrect, and it doesn't seem it is the system's responsibility to protect
against a "programming error".
The call to SysBeep should have been bracketed with the appropriate
Get/SetGWorld calls to save and restore the port AND the graphic device.
Actually, the System crashed because the graphic device for the monitor the
menubar is on was not the currently active graphic device, I suspect.
If Apple fixed SysBeep to be self protecting, then a jillion other routines
would deserve upgrade. So you can see the problem.
It sounds like I am saying it is your friend's fault, :) but actually it is the
fault of less-than-adequate information management and accessibility here in
the future. We developers have to know too much, and have yet to really use
our computers to help alleviate this burden in a coordinated way.
Hope this helps.
Mark Hanrek
The Information Workshop
+++++++++++++++++++++++++++
>From rmah@panix.com (Robert S. Mah)
Date: Sat, 12 Mar 1994 10:13:04 -0500
Organization: One Step Beyond
markhanrek@aol.com (MarkHanrek) wrote:
> [...]
> The call to SysBeep should have been bracketed with the appropriate
> Get/SetGWorld calls to save and restore the port AND the graphic device.
>[...]
I have to disagree. If SysBeep() normally affected the screen then, yes,
it should be the application programmers responsibility to set/restore
the GWorld, but the menu bar flashing behaviour is a special case inside
SysBeep() and not part of it's "standard" behaviour. Thus, it is SysBeep
that should be setting/restoring the GWorld.
Of course, given the existance of this bug, the point is mute as the app
programmer _must_ set/restore the GWorld when calling SysBeep() in order
to have his stuff work. C'est la vie.
Cheers,
Rob
________________________________________________________________________
Robert S. Mah One Step Beyond rmah@panix.com
+++++++++++++++++++++++++++
>From tgreen@ersys.edmonton.ab.ca (Terry Greeniaus)
Date: Sun, 13 Mar 94 15:42:40 MST
Organization: Edmonton Remote Systems #2
rmah@panix.com (Robert S. Mah) writes:
> markhanrek@aol.com (MarkHanrek) wrote:
>
> > [...]
> > The call to SysBeep should have been bracketed with the appropriate
> > Get/SetGWorld calls to save and restore the port AND the graphic device.
> >[...]
>
> I have to disagree. If SysBeep() normally affected the screen then, yes,
> it should be the application programmers responsibility to set/restore
> the GWorld, but the menu bar flashing behaviour is a special case inside
> SysBeep() and not part of it's "standard" behaviour. Thus, it is SysBeep
> that should be setting/restoring the GWorld.
>
> Of course, given the existance of this bug, the point is mute as the app
> programmer _must_ set/restore the GWorld when calling SysBeep() in order
> to have his stuff work. C'est la vie.
>
> Cheers,
> Rob
Well, if you're worried, at the start of your application, you could
check the sound level and see if it was zero. Then set a Boolean
variable to true if it is non-zero or false if it is zero. Then you
could write some routine:
void MySysBeep()
{
if (beepFlag)
SysBeep(1);
else
{
// Either save the current GWorld or not beep at all
// SysBeep();
// Reset the current GWorld
}
}
and then replace all your calls to SysBeep(1) with MySysBeep(); .
There ya go! :-)
"Yes, I have tricks in my pocket, I have things up my sleeve. But I am
the opposite of a stage magician. He gives you illusion that has the
appearance of truth. I give you truth in the pleasant disguise of
illusion."
--Tom Wingfield
from "The Glass Menagerie" by T. Williams
+++++++++++++++++++++++++++
>From Ralph Martin <Ralph.Martin@cm.cf.ac.uk>
Date: Mon, 14 Mar 1994 16:22:13 +0000
Organization: University of Wales College of Cardiff
In article <T0D6ic3w165w@ersys.edmonton.ab.ca> Terry Greeniaus,
tgreen@ersys.edmonton.ab.ca writes:
>Well, if you're worried, at the start of your application, you could
>check the sound level and see if it was zero. Then set a Boolean
>variable to true if it is non-zero or false if it is zero. Then you
>could write some routine:
>void MySysBeep()
>{
> if (beepFlag)
> SysBeep(1);
> else
> {
> // Either save the current GWorld or not beep at all
> // SysBeep();
> // Reset the current GWorld
> }
>}
>and then replace all your calls to SysBeep(1) with MySysBeep(); .
And then when the user changes the sound level AFTER your program has
started?
Kaboom...
+++++++++++++++++++++++++++
>From jwbaxter@olympus.net (John W. Baxter)
Date: Mon, 14 Mar 1994 09:06:57 -0800
Organization: Internet for the Olympic Peninsula
In article <T0D6ic3w165w@ersys.edmonton.ab.ca>, tgreen@ersys.edmonton.ab.ca
(Terry Greeniaus) wrote:
Discussion of the need to save/restore GWorlds before SysBeep () omitted
>
> Well, if you're worried, at the start of your application, you could
> check the sound level and see if it was zero. Then set a Boolean
> variable to true if it is non-zero or false if it is zero. Then you
> could write some routine: [omitted]
Not at the start of the application: the user can change the sound level
any time your app calls WaitNextEvent (). YOU wouldn't do that...but the
whole point of the exercise is to make your code work on other people's
machines.
--
John Baxter Port Ludlow, WA, USA [West shore, Puget Sound]
jwbaxter@pt.olympus.net
+++++++++++++++++++++++++++
>From jim_reekes@quickmail.apple.com (Jim Reekes)
Date: Tue, 15 Mar 1994 06:29:45 GMT
Organization: Apple Computer, Inc.
In article <rmah-120394101304@rmah.dialup.access.net>, rmah@panix.com
(Robert S. Mah) wrote:
>
> markhanrek@aol.com (MarkHanrek) wrote:
>
> > [...]
> > The call to SysBeep should have been bracketed with the appropriate
> > Get/SetGWorld calls to save and restore the port AND the graphic device.
> >[...]
>
> I have to disagree. If SysBeep() normally affected the screen then, yes,
> it should be the application programmers responsibility to set/restore
> the GWorld, but the menu bar flashing behaviour is a special case inside
> SysBeep() and not part of it's "standard" behaviour. Thus, it is SysBeep
> that should be setting/restoring the GWorld.
>
> Of course, given the existance of this bug, the point is mute as the app
> programmer _must_ set/restore the GWorld when calling SysBeep() in order
> to have his stuff work. C'est la vie.
Well, I wrote SysBeep and I simply use the following code.
FlashMenuBar(0); // just flash entire menu bar
Delay(kMenuBarDelayTime, &finalTick);
FlashMenuBar(0);
If anyone is NOT saving/restoring the GWorlds, it could be the Menu
Manager.
I missed the original message, but this is not a sound manager bug.
- ---------------------------------------------------------------------
Jim Reekes, Polterzeitgeist | Macintosh Toolbox Engineering
| Sound Manager Expert
Apple Computer, Inc. | "All opinions expressed are mine, and do
20525 Mariani Ave. MS 302-3KS | not necessarily represent those of my
Cupertino, CA 95014 | employer, Apple Computer Inc."
+++++++++++++++++++++++++++
>From qsi@cnh.wlink.nl (Peter Kocourek)
Date: Tue, 15 Mar 1994 00:04:37 +0100
Organization: (none)
Terry Greeniaus wrote:
TG> Well, if you're worried, at the start of your application,
TG> you could check the sound level and see if it was zero. Then
TG> set a Boolean variable to true if it is non-zero or false if
TG> it is zero. Then you could write some routine:
No, you should check the sound level every time just before the SysBeep,
because users can and do change the sound level while your app is running.
YHS:QSI!
+++++++++++++++++++++++++++
>From KLUEV@jonathan.srcc.msu.su
Date: Wed, 16 Mar 1994 21:02:49 +0300
Organization: (none)
In article <763696813.AA01334@cnh.wlink.nl>
qsi@cnh.wlink.nl (Peter Kocourek) writes:
>Terry Greeniaus wrote:
>
> TG> Well, if you're worried, at the start of your application,
> TG> you could check the sound level and see if it was zero. Then
> TG> set a Boolean variable to true if it is non-zero or false if
> TG> it is zero. Then you could write some routine:
>
>No, you should check the sound level every time just before the SysBeep,
>because users can and do change the sound level while your app is running.
(SoundLevel <> 0) doesn't lead to (There will be sound, and not flash).
Michael Kluev.
---------------------------
>From ViviStar@ACM.org (Jonathan Hess)
Subject: PPC & 68k UPP problems
Date: Tue, 1 Mar 1994 00:56:35 GMT
Organization: ViviStar Consulting
I've reviewed "Making the Leap to PowerPC" article in develop 16 but
find its description of Universal ProcPtrs lacking. Particularly in
relation to coding source that is compatible with both 68k and PowerPC
systems.
Using the code snippets from that article would lead one to believe
that a global declaration of:
RoutineDescriptor gVActionProcRD = BUILD_ROUTINE_DESCRIPTOR(
uppControlActionProcInfo, VActionProc);
with code such as:
TrackControl(ctlHit, mouseLoc, (ControlActionUPP) &gVActionProcRD);
would work under both PowerPC and 68k systems. While this might work
with PowerPC systems it clearly will not work with 68k systems --
VActionProc should be passed in the TrackControl call but taking the
address of gVActionProcRD can not possibly return that appropriate
address.
Anyone have some sample code you could link me or that I could ftp from
somewhere?
Thanks,
Jonathan Hess
ViviStar Consulting
+++++++++++++++++++++++++++
>From zstern@adobe.com (Zalman Stern)
Date: Tue, 1 Mar 1994 12:25:29 GMT
Organization: Adobe Systems Incorporated
Jonathan Hess writes
> I've reviewed "Making the Leap to PowerPC" article in develop 16 but
> find its description of Universal ProcPtrs lacking. Particularly in
> relation to coding source that is compatible with both 68k and PowerPC
> systems.
>
> Using the code snippets from that article would lead one to believe
> that a global declaration of:
>
> RoutineDescriptor gVActionProcRD = BUILD_ROUTINE_DESCRIPTOR(
> uppControlActionProcInfo, VActionProc);
>
> with code such as:
>
> TrackControl(ctlHit, mouseLoc, (ControlActionUPP) &gVActionProcRD);
>
> would work under both PowerPC and 68k systems. While this might work
> with PowerPC systems it clearly will not work with 68k systems --
> VActionProc should be passed in the TrackControl call but taking the
> address of gVActionProcRD can not possibly return that appropriate
> address.
>
> Anyone have some sample code you could link me or that I could ftp from
> somewhere?
I'd do something like this. In a header file have the following:
#if NEEDROUTINEDESCRIPTORS
#define MakeStaticRoutineDesc(name, procinfo) \
RoutineDescriptor name##RDS = \
BUILD_ROUTINE_DESCRIPTOR(procinfo, name);
#else
#define MakeStaticRoutineDesc(name, procinfo)
#endif
#if NEEDROUTINEDESCRIPTORS
#define ExternRoutineDescriptor(name) \
extern RoutineDescriptor name##RDS;
#else
#define ExternRoutineDesc(name)
#ednif
#if NEEDROUTINEDESCRIPTORS
#define ConditionalRD(name) (&name##RDS)
#else
#define ConditionalRD(name) (&name)
#endif
To use this write code like so:
pascal void VActionProc(ControlHandle theControl, short partCode)
{
/* ... */
}
MakeStaticRoutineDesc(VActionProc, uppControlActionProcInfo)
{
TrackControl(ctlHit, mouseLoc, (ControlActionUPP)
ConditionalRD(VActionProc));
}
The ExternRoutineDesc macro is used in addition to existing extern
prototypes in header files. (Ideally, the Apple header files would declare a
direct function type for each callback in addition to the function pointer
type, but they don't. If they did, ExternRoutineDesc could declare either a
function or a RoutineDescriptor structure.)
--
Zalman Stern zalman@adobe.com (415) 962 3824
Adobe Systems, 1585 Charleston Rd., POB 7900, Mountain View, CA 94039-7900
"Do right, and risk consequences." Motto of Sam Houston (via Molly Ivins)
+++++++++++++++++++++++++++
>From d88-jwa@mumrik.nada.kth.se (Jon Wdtte)
Date: 1 Mar 1994 19:50:23 GMT
Organization: Royal Institute of Technology, Stockholm, Sweden
In <CLynyC.G8v@news.direct.net> ViviStar@ACM.org (Jonathan Hess) writes:
>Using the code snippets from that article would lead one to believe
>that a global declaration of:
> RoutineDescriptor gVActionProcRD = BUILD_ROUTINE_DESCRIPTOR(
> uppControlActionProcInfo, VActionProc);
>would work under both PowerPC and 68k systems. While this might work
>with PowerPC systems it clearly will not work with 68k systems --
>VActionProc should be passed in the TrackControl call but taking the
>address of gVActionProcRD can not possibly return that appropriate
>address.
No, but it might be that under the 68k environment, the routine
descriptor includes a JMP instruction and the address...
However, that doesn't appear to be the case; instead, you're
supposed to call NewControlActionProc which WILL work on both
kinds of systems.
Cheers,
/ h+
--
-- Jon W{tte, h+@nada.kth.se, Mac Hacker Deluxe --
"Don't use the Layer Manager"
+++++++++++++++++++++++++++
>From t-gaul@i-link.com (Troy Gaul)
Date: Wed, 02 Mar 1994 15:29:32 -0600
Organization: I-Link, Ltd.
In article <2l069v$mt4@news.kth.se>, d88-jwa@mumrik.nada.kth.se (Jon Wtte)
wrote:
> In <CLynyC.G8v@news.direct.net> ViviStar@ACM.org (Jonathan Hess) writes:
>
> >Using the code snippets from that article would lead one to believe
> >that a global declaration of:
>
> > RoutineDescriptor gVActionProcRD = BUILD_ROUTINE_DESCRIPTOR(
> > uppControlActionProcInfo, VActionProc);
>
> >would work under both PowerPC and 68k systems. While this might work
> >with PowerPC systems it clearly will not work with 68k systems --
> >VActionProc should be passed in the TrackControl call but taking the
> >address of gVActionProcRD can not possibly return that appropriate
> >address.
>
> No, but it might be that under the 68k environment, the routine
> descriptor includes a JMP instruction and the address...
>
> However, that doesn't appear to be the case; instead, you're
> supposed to call NewControlActionProc which WILL work on both
> kinds of systems.
Yeah, but that creates it in the heap (on PowerPC), not on the stack, which
can be advantageous at times. Zalman Stern recently posted a technique in
this thread that allows you to create a static routine descriptor, which it
looked like, would also work for stack-based RDs.
This can be useful for things like DeviceLoop drawing procs that don't have
to stay around for long to avoid creating and disposing in the heap all of
the time (in code like a WDEF that, on the 68K, can't have global data -- I
know that it can on the PowerPC, but I wanted to do it in a portable way
for if/when RDs are supported on 68K).
_troy
//////// //////___Troy Gaul_________________________t-gaul@i-link.com__ //
// // I-Link, Ltd. ; West Des Moines, Iowa //
// // // "Iungo ergo sum." (I-Link, therefore I am.) //
// //////________________________________________________________ //
---------------------------
>From arose@ATHENA.MIT.EDU (Alex Rosen)
Subject: PPC binaries
Date: 7 Mar 1994 17:05:23 GMT
Organization: Massachusetts Institute of Technology
(1) Since PPC code is in the data fork and 68k code is in the resource
fork: Would it be possible to embed a tiny 68k app in my PPC app,
which just pops up a dialog saying "This program is for PPC computers,
please install the 68k version" or something like that?
(2) I assume that CodeWarrior and the Apple SDK don't use any of the
instructions on the 601 that aren't part of the PPC spec, and that may
not be around on future chips. Is this so? Might these instructions be
emulated via traps on future chips?
(3) Has Apple said anything about low memory globals on PPC? If Apple
were to release a system with memory protection, it would seem that all
apps which access LMGs directly would break, and there are plenty of
these apps around. But it seems that recompiling for PPC is the perfect
time for developers to replace this code with system software calls
(e.g. GetMBarHeight(), SetMBarHeight() ). Any word from Apple on this?
--Alex
+++++++++++++++++++++++++++
>From d88-jwa@mumrik.nada.kth.se (Jon Wdtte)
Date: 7 Mar 1994 19:13:25 GMT
Organization: Royal Institute of Technology, Stockholm, Sweden
In <2lfmsj$otv@senator-bedfellow.MIT.EDU> arose@ATHENA.MIT.EDU (Alex Rosen) writes:
>(1) Since PPC code is in the data fork and 68k code is in the resource
>fork: Would it be possible to embed a tiny 68k app in my PPC app,
>which just pops up a dialog saying "This program is for PPC computers,
>please install the 68k version" or something like that?
It's not only possible, it's THE LAW, unless you shiip a fat
binary.
Now, should you embed a tiny PEF that says "this application is only
for 68k Macs" ? :-)
There is sample code on the SDK to show this, though it's really
as trivial as building:
void
main ( void ) {
InitGraf ( & qd . thePort ) ;
InitFonts ( ) ;
InitWindows ( ) ;
InitMenus ( ) ;
TEInit ( ) ;
InitDialogs ( ) ;
Alert ( 666 , NULL ) ;
}
and pasting your app resources into the native (nee, "optimized")
app.
>(2) I assume that CodeWarrior and the Apple SDK don't use any of the
>instructions on the 601 that aren't part of the PPC spec, and that may
>not be around on future chips. Is this so? Might these instructions be
>emulated via traps on future chips?
They're all clean.
>(3) Has Apple said anything about low memory globals on PPC? If Apple
Yeah, they're still there (if you call LMGetCurDeactive() or LMSetXXX)
However, in the future, the programming model might rid itself of
lo-mem globals.
--
-- Jon W{tte, h+@nada.kth.se, Mac Hacker Deluxe --
There's no problem that can't be solved using brute-force algorithms
and a sufficiently fast computer. Ergo, buy more hardware. (NOT!)
+++++++++++++++++++++++++++
>From gdl@stlawrence.maths (Mr_G._Landweber_student_tel_2-73550)
Date: 07 Mar 1994 23:38:36 GMT
Organization: (none)
In article <2lfmsj$otv@senator-bedfellow.MIT.EDU> arose@ATHENA.MIT.EDU (Alex Rosen) writes:
(3) Has Apple said anything about low memory globals on PPC? If Apple
were to release a system with memory protection, it would seem that all
apps which access LMGs directly would break, and there are plenty of
these apps around. But it seems that recompiling for PPC is the perfect
time for developers to replace this code with system software calls
(e.g. GetMBarHeight(), SetMBarHeight() ). Any word from Apple on this?
As of the first PowerMacs, all the low memory globals--both documented
and not--are still there. However, the universal header files for
compling PowerPC native (and 680x0) apps no longer define these
globals. They use "Get..." and "Set..." macros instead.
-- Greg "Buttons" Landweber
gdl@maths.ox.ac.uk
+++++++++++++++++++++++++++
>From DACRXL01.OURX124@tcp30.dx.deere.com (Juan Ingles)
Date: Tue, 8 Mar 1994 18:16:12 GMT
Organization: Proteus Ventures, Inc.
In article <2lfucm$21c@news.kth.se>
d88-jwa@mumrik.nada.kth.se (Jon Wdtte) writes:
> void
> main ( void ) {
> InitGraf ( & qd . thePort ) ;
> InitFonts ( ) ;
> InitWindows ( ) ;
> InitMenus ( ) ;
> TEInit ( ) ;
> InitDialogs ( ) ;
> Alert ( 666 , NULL ) ;
> }
InitDialogs ( ) should be: InitDialogs ( NULL )
Tsk... Tsk... Jon, you forgot your resumeProc Ptr. :)
>--
> -- Jon W{tte, h+@nada.kth.se, Mac Hacker Deluxe --
>There's no problem that can't be solved using brute-force algorithms
>and a sufficiently fast computer. Ergo, buy more hardware. (NOT!)
There's no code that can't be optimized. Ergo, spend the rest of your
life optimizing code, and in the end the code won't take any time to
run at all. ;)
Juan Ingles
<DACRXL01.OURX124@tcp30.dx.deere.com>
--
Proteus Ventures, Inc. - Computer Software Consulting and Development
1514 Oriole Ave * Waterloo, IA 50701 * (319) 232-0985
+++++++++++++++++++++++++++
>From ejf0@ns1.cc.lehigh.edu (EUGENE JOSEPH FOSS)
Date: Thu, 10 Mar 1994 03:34:55 GMT
Organization: Lehigh University
Jon Wdtte (d88-jwa@mumrik.nada.kth.se) wrote:
: Now, should you embed a tiny PEF that says "this application is only
: for 68k Macs" ? :-)
Well, you could if you wanted too, but wouldn't it be a little silly? I mean,
since all the PPC Macs include 68k emulation...
--
Eugene Foss CS/Math/Cog. Sci.
---------------------------------------------------------------------
"Eating meat on Fridays may not be a mortal sin anymore, but I
bet there are still some guys in hell doing time on a meat rap."
+++++++++++++++++++++++++++
>From d88-jwa@mumrik.nada.kth.se (Jon Wdtte)
Date: 10 Mar 1994 10:30:50 GMT
Organization: Royal Institute of Technology, Stockholm, Sweden
>: Now, should you embed a tiny PEF that says "this application is only
>: for 68k Macs" ? :-)
>Well, you could if you wanted too, but wouldn't it be a little silly? I mean,
>since all the PPC Macs include 68k emulation...
There WAS a smiley there after all.
The more relevant reason being there may be a PPC version, and
users should know they're losing out on performance.
So, your installer could choose between installing
1) Full fat binary
2) PPC code with tiny 68k alert
3) 68k code with tiny PEF alert
Cheers,
/ h+
--
-- Jon W{tte, h+@nada.kth.se, Mac Hacker Deluxe --
The word "politics" is derived from the word "poly", meaning
"many", and the word "ticks", meaning "blood sucking parasites".
-- Larry Hardiman
+++++++++++++++++++++++++++
>From zstern@adobe.com (Zalman Stern)
Date: Thu, 10 Mar 1994 18:59:10 GMT
Organization: Adobe Systems Incorporated
Jon W tte writes
>
> >: Now, should you embed a tiny PEF that says "this application is only
> >: for 68k Macs" ? :-)
>
> >Well, you could if you wanted too, but wouldn't it be a little silly? I
mean,
> >since all the PPC Macs include 68k emulation...
>
> There WAS a smiley there after all.
>
> The more relevant reason being there may be a PPC version, and
> users should know they're losing out on performance.
>
> So, your installer could choose between installing
> 1) Full fat binary
> 2) PPC code with tiny 68k alert
> 3) 68k code with tiny PEF alert
Its just as easy to gestalt for the PowerPC in your 68k code. However, there
is an interesting question there about how one should differentiate between
running PowerPC and 68K code. A good solution is to put something in the
splash screen. (At least for apps with heavy weight splash screens.)
Likewise, this would appear in the about box. The question is what should be
there?
--
Zalman Stern zalman@adobe.com (415) 962 3824
Adobe Systems, 1585 Charleston Rd., POB 7900, Mountain View, CA 94039-7900
"Do right, and risk consequences." Motto of Sam Houston (via Molly Ivins)
---------------------------
>From gewekean@studentg.msu.edu (Andrew Geweke)
Subject: Passing data through to completion procs?
Date: Wed, 16 Mar 1994 22:06:40 -0500
Organization: Michigan State University
What I'm doing is writing an interface library to MacTCP; I want it to be
simple. All routines are async, so I just want to have the caller pass in a
simple structure pointer; a field in the struct gets changed when the call
completes. I want to do this rather than having the user ravage through large
ParamBlocks and so forth for simplicity and so on.
My question is this: How can I get the Device Manager to pass four bytes to a
completion routine that I pass in when I make the call?
Basically, I'm having trouble getting a pointer to the structure through to
the completion routine. Is there any place I can stash this? I'm looking
through the ParamBlock structure right now, and everything's used or "not
used" (which, as we all know, means reserved -- I don't want to break rules
here).
Here are my ideas so far:
(1) Set the user up with a pointer to the ioResult field. Disadvantage: I
want to deallocate the parameter-block's memory as soon as the call
completes. This would require the user to do this.
(2) Create a linked list of all outstanding calls with pointers to their
parameter blocks. This is a roundabout method, though it should work;
however, I'd rather not.
Basically, I'm converting async calls from the beasts that they are into
simple ones; you pass in a struct with only the specific information that
gets a flag set when it's done. Any ideas?
+++++++++++++++++++++++++++
>From resnick@cogsci.uiuc.edu (Pete Resnick)
Date: Thu, 17 Mar 1994 01:37:49 -0600
Organization: University of Illinois at Urbana-Champaign
In article <9403162206.AA40375@geweke.ppp.msu.edu>,
gewekean@studentg.msu.edu (Andrew Geweke) wrote:
>What I'm doing is writing an interface library to MacTCP;
>
>My question is this: How can I get the Device Manager to pass four bytes to a
>completion routine that I pass in when I make the call?
>
>Basically, I'm having trouble getting a pointer to the structure through to
>the completion routine. Is there any place I can stash this?
Since you're using MacTCP, you're in luck. Every MacTCP param block has a
userDataPtr field, which is exactly where you can store any pointer you
like.
Even if this field weren't there, you can do the same thing. Just make
your own personal parameter block which contains everything the real
parameter block does, plus one pointer field tacked onto the end. The
Device Manager and driver are only going to use the fields they specify,
so this is perfectly safe. (How could it not be? It would be quite ugly if
a device driver decided to use some memory past the end of its parameter
block!)
pr
--
Pete Resnick (...so what is a mojo, and why would one be rising?)
Graduate assistant - Philosophy Department, Gregory Hall, UIUC
System manager - Cognitive Science Group, Beckman Institute, UIUC
Internet: resnick@cogsci.uiuc.edu
+++++++++++++++++++++++++++
>From zben@ni.umd.edu (Charles B. Cranston)
Date: 18 Mar 1994 00:50:47 GMT
Organization: UMCP Network Infrastructures
In article <9403162206.AA40375@geweke.ppp.msu.edu>,
gewekean@studentg.msu.edu (Andrew Geweke) wrote:
> What I'm doing is writing an interface library to MacTCP; I want it to be
> simple. All routines are async, so I just want to have the caller pass in a
> simple structure pointer; a field in the struct gets changed when the call
> completes. I want to do this rather than having the user ravage through large
> ParamBlocks and so forth for simplicity and so on.
> My question is this: How can I get the Device Manager to pass four bytes to a
> completion routine that I pass in when I make the call?
Another approach would be to erect a "trampoline" somewhere. This would
be 8 bytes consisting of a JSr to the real handler followed by the four
data bytes. The real handler immediately does a Move.L (A7)+,A0 and then
A0 points to the four data bytes, and the stacktop is now the real final
return address.
For MacTCP the UserData approach or the embed-IOPB-in-larger-known-block
approaches would both work. I am thinking about using this trampoline
technique for EtherNet "Protocol Handlers" where the IOPB is not passed
to the callback routine.
The cost, of course, is allocating and freeing the memory space for
the trampoline, especially in the asynchronous environment you are
talking about.
---------------------------
>From Dmitry Boldyrev <dmitry@atlas.chem.utah.edu>
Subject: Password editing item.. Tricky?
Date: 23 Feb 1994 02:22:25 GMT
Organization: University of Utah
Hi All.
I am wounding if anyone has implemented so called scrambled editing item
I looked at the ftp.apple.com and found a couple of codes which would do
it
but, I don't think it is the best way to do..
I am gonna use it for my FTP client. so, when I type my password "hello"
it should actually print on the display "!!!!!". and the buffer should
have "hello" so that I can then use it.
I am thinking that there should be a way of writing a small routine and
hook the interruption and everything what supposed to be displayed will
be taken care by that routine..
Any ideas how it can be implemented? (Pascal, C iz ok)
Thank you very much!
......................................................................
. Dmitry Boldyrev . (_) (_) .
. University of Utah, Salt Lake City . |---| urricane, inc .
. Utah, USA . (_) (_) .
. Home Tel: (801) 581-1298, Office Tel: (801) 581-5465 .
......................................................................
+++++++++++++++++++++++++++
>From infosafe@panix.com (Tom Lipscomb)
Date: 22 Feb 1994 23:57:18 -0500
Organization: PANIX Public Access Internet and Unix, NYC
The easiest solution I came up with was to make my own font, which had
one character (a diamond) for all of the letters. Use this font for
the edit text that they are typing the password in.
Cheers,
Bradford Smith
+++++++++++++++++++++++++++
>From Jonathan D Baumgartner <Jonathan.D.Baumgartner@unh.edu>
Date: 23 Feb 1994 15:11:37 GMT
Organization: Computing & Information Services, University of New Hampshire
In article <2kenne$rku@panix2.panix.com> Tom Lipscomb, infosafe@panix.com
writes:
>The easiest solution I came up with was to make my own font, which had
>one character (a diamond) for all of the letters. Use this font for
>the edit text that they are typing the password in.
That's an interesting solution; wish I'd thought of that earlier :-)
I did this by creating a dialog filter which I pass to ModalDialog. When
a keyDown or autoKey event occurs, it takes the character, appends it to
a dummy string, and then changes the EventRecord's message to a bullet.
This way you end up with a string that holds the password, but the user
only sees bullets on-screen.
I found a really excellent example (but HUGE, and it does a lot of other
stuff besides) in the source for John Norstad's NewsWatcher.
jon
--
Jonathan D. Baumgartner Jonathan.D.Baumgartner@unh.edu
Computing & Information Services, University of New Hampshire
"It's just a matter of opinion." -- Primus
+++++++++++++++++++++++++++
>From Scott_Gruby@hmc.edu (Scott Gruby)
Date: Wed, 23 Feb 1994 07:34:32 -0800
Organization: Harvey Mudd College, Claremont CA
In article <2kfrn9$d4v@mozz.unh.edu>, Jonathan D Baumgartner
<Jonathan.D.Baumgartner@unh.edu> wrote:
> I did this by creating a dialog filter which I pass to ModalDialog. When
> a keyDown or autoKey event occurs, it takes the character, appends it to
> a dummy string, and then changes the EventRecord's message to a bullet.
> This way you end up with a string that holds the password, but the user
> only sees bullets on-screen.
>
> I found a really excellent example (but HUGE, and it does a lot of other
> stuff besides) in the source for John Norstad's NewsWatcher.
>
There's a snippet on ftp.apple.com that shows 3 ways of doing this; 1 is
with a different font, 1 is as you described and I forgot what the 3rd one
was. Anyway there is an example that is really SMALL and very easy to
understand.
--
Scott Allen Gruby (Scott_Gruby@hmc.edu)
Macintosh Student System Manager
Academic Computing, Harvey Mudd College
Claremont, CA 91711
+++++++++++++++++++++++++++
>From mwalker@netcom.com (Mel Walker)
Date: Wed, 23 Feb 1994 17:01:30 GMT
Organization: Committee to Elect Dan Quayle Lord of the Cosmos
Dmitry Boldyrev (dmitry@atlas.chem.utah.edu) wrote:
: Hi All.
: I am wounding if anyone has implemented so called scrambled editing item
: I looked at the ftp.apple.com and found a couple of codes which would do
: it
: but, I don't think it is the best way to do..
: I am gonna use it for my FTP client. so, when I type my password "hello"
: it should actually print on the display "!!!!!". and the buffer should
: have "hello" so that I can then use it.
: I am thinking that there should be a way of writing a small routine and
: hook the interruption and everything what supposed to be displayed will
: be taken care by that routine..
: Any ideas how it can be implemented? (Pascal, C iz ok)
: Thank you very much!
My prefered way is to have two text boxes for the password, one of which
is outside of the dialog (i.e., it's invisible). Use a filter routine in
your modal dialog that puts keystrokes into the invisible field, and puts
a ! into the visible field. Backspaces, selections, and the like affect
both fields.
I may be explaining this badly. Send me email if you want more help.
--
Mel Walker mwalker@netcom.com
"Natural exuberance is one of those qualities that makes us tigers so
darn endearing!" -- Hobbes
+++++++++++++++++++++++++++
>From Dmitry Boldyrev <dmitry@atlas.chem.utah.edu>
Date: 23 Feb 1994 18:27:43 GMT
Organization: University of Utah
In article <2kfrn9$d4v@mozz.unh.edu> Jonathan D Baumgartner,
Jonathan.D.Baumgartner@unh.edu writes:
>That's an interesting solution; wish I'd thought of that earlier :-)
>
>I did this by creating a dialog filter which I pass to ModalDialog. When
>a keyDown or autoKey event occurs, it takes the character, appends it to
>a dummy string, and then changes the EventRecord's message to a bullet.
>This way you end up with a string that holds the password, but the user
>only sees bullets on-screen.
>
>I found a really excellent example (but HUGE, and it does a lot of other
>stuff besides) in the source for John Norstad's NewsWatcher.
Yeah, I know about the way of making such a font.. looks like it is the
only
solution I can think of. I've done the same way as Johnatan described, but
there iz a little problem. Suppose you want to show a password when you
create
a window.. How would you do it?
like I want !!!!!! to be shown when the dialog appears.. they way you
suggest
it it won't work.
Thanks for the replies, guys!
+++++++++++++++++++++++++++
>From Dmitry Boldyrev <dmitry@atlas.chem.utah.edu>
Date: 23 Feb 1994 18:28:57 GMT
Organization: University of Utah
In article <2kenne$rku@panix2.panix.com> Tom Lipscomb, infosafe@panix.com
writes:
>The easiest solution I came up with was to make my own font, which had
>one character (a diamond) for all of the letters. Use this font for
>the edit text that they are typing the password in.
>
>Cheers,
>Bradford Smith
A little problem too.
How would you do it if you have two editing items?
When you change the font, it will make all TE items the same font.. ?
Thanks
Dmitry.
+++++++++++++++++++++++++++
>From hrafal@copernicus.bbn.com (Howie Rafal)
Date: 23 Feb 1994 19:24:30 GMT
Organization: BBN, Inc
In article <2kenne$rku@panix2.panix.com>, infosafe@panix.com (Tom Lipscomb)
wrote:
>
> The easiest solution I came up with was to make my own font, which had
> one character (a diamond) for all of the letters. Use this font for
> the edit text that they are typing the password in.
>
> Cheers,
> Bradford Smith
Be careful to not allow copy in the item, because it could be pasted
somewhere else and the font changed.
I use a TCL class called CPasswordText that I could forward to you if you
want. It actually uses a bullet character and maintains a text item
offscreen. I also have classes for password dialogs which handle turning
on and off the OK button based on the login fields having values entered.
HOWIE.
+++++++++++++++++++++++++++
>From peter@ncrpda.curtin.edu.au (Peter N Lewis)
Date: 24 Feb 1994 10:39:33 +0800
Organization: NCRPDA, Curtin University
infosafe@panix.com (Tom Lipscomb) writes:
>The easiest solution I came up with was to make my own font, which had
>one character (a diamond) for all of the letters. Use this font for
>the edit text that they are typing the password in.
Don't spaces show up though? Last time I tried this, the spaces showed up
even if your font didn't define the space character or even if you did,
it would show up as a space. This was a long time back, maybe its changed?
Peter.
--
_______________________________________________________________________
Peter N Lewis <peter.lewis@info.curtin.edu.au> Ph: +61 9 368 2055
+++++++++++++++++++++++++++
>From Jonathan D Baumgartner <Jonathan.D.Baumgartner@unh.edu>
Date: 24 Feb 1994 18:24:47 GMT
Organization: Computing & Information Services, University of New Hampshire
In article <2kg76v$bei@u.cc.utah.edu> Dmitry Boldyrev,
dmitry@atlas.chem.utah.edu writes:
>Yeah, I know about the way of making such a font.. looks like it is the
>only
>solution I can think of. I've done the same way as Johnatan described,
but
>there iz a little problem. Suppose you want to show a password when you
>create
>a window.. How would you do it?
>like I want !!!!!! to be shown when the dialog appears.. they way you
>suggest
>it it won't work.
Um, you mean you want the password to show up as a series of !s before
anything is typed? Like a default password or something?
Assuming that's what you mean, I just use GetDItem() and SetIText(). Get
a handle to the edit text field with GetDItem(), and then use SetIText()
to change the text to an appropriate number of !s.
(Appropriate number in this case would be the length of the actual
password.)
jon
--
Jonathan D. Baumgartner Jonathan.D.Baumgartner@unh.edu
Computing & Information Services, University of New Hampshire
"It's just a matter of opinion." -- Primus
+++++++++++++++++++++++++++
>From f8dy@access.netaxs.com (Mark Pilgrim)
Date: 24 Feb 1994 22:22:38 GMT
Organization: Net Access - Philadelphia's Internet Connection
Peter N Lewis (peter@ncrpda.curtin.edu.au) wrote:
: infosafe@panix.com (Tom Lipscomb) writes:
: >The easiest solution I came up with was to make my own font, which had
: >one character (a diamond) for all of the letters. Use this font for
: >the edit text that they are typing the password in.
: Don't spaces show up though? Last time I tried this, the spaces showed up
: even if your font didn't define the space character or even if you did,
: it would show up as a space. This was a long time back, maybe its changed?
: Peter.
Peter, you are correct. Tom, the one (potential) problem with your method
is that one could copy the password to the clipboard and paste it somewhere
else in a different font -- especially a problem if the dialog box is
coming up with a password already there (in diamonds or bullets or bangs).
After much agonizing over this issue, I finally went with the "editable
text item outside the frame of the dialog" approach. I did _not_ have a
second text item that mirrored the first one with bullets(/diamonds/bangs);
instead, I displayed a character count (similar to Compact Pro) which
updated with every keypress to the length of the editable text box. (This
covers the situation of a user pasting in a password and/or cutting part of
it out, where the length of the password may change by more than +-1.) And
I had checkboxes to hide/show the character count and hide/show the password
itself -- both of which should be saved a preferences and restored the next
time the user has to enter a password.
Of course, this doesn't solve the problem of having a password there when
the dialog box comes up, since you could just check "show password" and see
it. (: But having a password there is an inherent security weakness. I
have discovered the password to an Appletalk server in the Chooser because
the password was "there" but expressed in bullet characters (i.e. copying
and pasting just yields bullets). Replacing one character at a time and
seeing if it was still the right password gave me the password in less than
a minute. (Of course, I assumed standard character frequencies and the
password happened to be "tres", but it's still a bad assumption that just
because the dialog box contains bullet characters that the underlying
password is safe.)
--
Mark Pilgrim | f8dy@netaxs.com | Please do not worry the philosophers.
"I can't say enough about the importance of brevity."
+++++++++++++++++++++++++++
>From ez015670@hamlet.ucdavis.edu ()
Date: Fri, 25 Feb 1994 00:33:49 GMT
Organization: University of California, Davis
Mark Pilgrim (f8dy@access.netaxs.com) wrote:
: Peter N Lewis (peter@ncrpda.curtin.edu.au) wrote:
: : Don't spaces show up though? Last time I tried this, the spaces showed up
: : even if your font didn't define the space character or even if you did,
: : it would show up as a space. This was a long time back, maybe its changed?
: : Peter.
: Peter, you are correct. Tom, the one (potential) problem with your method
Another potential security problem that has not been addressed is the picking
up of the password at a much lower level. I have made a program that
prints all the characters pressed to a file including passwords. Maybe
through a jGNE filter one could remove the characters before other inits
can get a hold of them.
Bret Olmsted
olmsted@cs.ucdavis.edu
+++++++++++++++++++++++++++
>From scott.m.silver@dartmouth.edu (Scott M. Silver)
Date: 25 Feb 1994 03:28:06 GMT
Organization: Dartmouth College - Hanover, NH
In article <CLr88E.C7F@ucdavis.edu>
ez015670@hamlet.ucdavis.edu () writes:
> Another potential security problem that has not been addressed is the picking
> up of the password at a much lower level. I have made a program that
> prints all the characters pressed to a file including passwords. Maybe
> through a jGNE filter one could remove the characters before other inits
> can get a hold of them.
This sort of seems to be one of those things where if "the person can
get to the computer-locally, then your data is not safe". (Unless it's
encrypted). Anyone can patch every single trap, write a jGNE filter,
etc and figure out what your password is (or get a program to watch you
type it in). Hell, they could video tape you typing it in.
Scott
____________________________________________________________________
Scott Silver Dartmouth College Hanover, NH
+++++++++++++++++++++++++++
>From d88-jwa@mumrik.nada.kth.se (Jon Wdtte)
Date: 24 Feb 1994 10:47:58 GMT
Organization: Royal Institute of Technology, Stockholm, Sweden
In <2kfrn9$d4v@mozz.unh.edu> Jonathan D Baumgartner <Jonathan.D.Baumgartner@unh.edu> writes:
>>The easiest solution I came up with was to make my own font, which had
>>one character (a diamond) for all of the letters. Use this font for
>>the edit text that they are typing the password in.
>That's an interesting solution; wish I'd thought of that earlier :-)
Because fonts in applications are a bad idea (for a number
of Font Manager reasons)
What I do is I patch the QuickDraw text measurement and text
drawing bottlenecks to measure a string of bullets instead of
the real string.
Cheers,
/ h+
--
-- Jon W{tte, h+@nada.kth.se, Mac Hacker Deluxe --
Not speaking for the Microsoft Corporation.
+++++++++++++++++++++++++++
>From infosafe@panix.com (Tom Lipscomb)
Date: 25 Feb 1994 01:11:10 -0500
Organization: PANIX Public Access Internet and Unix, NYC
In article <2kg799$bei@u.cc.utah.edu>,
Dmitry Boldyrev <dmitry@atlas.chem.utah.edu> wrote:
>In article <2kenne$rku@panix2.panix.com> Tom Lipscomb, infosafe@panix.com
>writes:
>>The easiest solution I came up with was to make my own font, which had
>>one character (a diamond) for all of the letters. Use this font for
>>the edit text that they are typing the password in.
>>
>>Cheers,
>>Bradford Smith
>
>A little problem too.
>How would you do it if you have two editing items?
>When you change the font, it will make all TE items the same font.. ?
>Thanks
>
>Dmitry.
For static text I made them User Items that drew the appropriate text in
Chicago. For the field where they typed the name, I set the font to
be Geneva, or something. For the field where I put the password, I set the
font to be .pwd font (or whatever it was). It's not the most secure
method; as lots of people pointed out, you can copy it to another field
and see what the text is.
For me this was not a concern, though. The person typed in the name and
pwd, it was accepted or rejected, and they moved on. The only person who
could have copied the text to another app was the person who just typed
it in -- not a security risk.
As for writing an init to catch the keystrokes -- anyone know how to stop it?
Cheers,
Bradford
+++++++++++++++++++++++++++
>From Jim.Matthews@dartmouth.edu (Jim Matthews)
Date: 25 Feb 1994 14:11:52 GMT
Organization: Dartmouth College
In article <2ki0ku$pir@news.kth.se>, d88-jwa@mumrik.nada.kth.se (Jon Wtte)
wrote:
> What I do is I patch the QuickDraw text measurement and text
> drawing bottlenecks to measure a string of bullets instead of
> the real string.
I tried that once but found it difficult to tell when StdText and StdMeas
were being called for the password, as opposed to anything else in the
dialog. Is there a sure-fire way to do this?
Jim Matthews
Dartmouth Software Development
+++++++++++++++++++++++++++
>From Mark.R.Valence@dartmouth.edu (kurash@dartmouth.edu)
Date: 25 Feb 1994 18:37:55 GMT
Organization: Dartmouth College, Hanover, NH
In article <Jim.Matthews-250294091049@ishmael.dartmouth.edu>
Jim.Matthews@dartmouth.edu (Jim Matthews) writes:
> In article <2ki0ku$pir@news.kth.se>, d88-jwa@mumrik.nada.kth.se (Jon Wtte)
> wrote:
>
> > What I do is I patch the QuickDraw text measurement and text
> > drawing bottlenecks to measure a string of bullets instead of
> > the real string.
>
> I tried that once but found it difficult to tell when StdText and StdMeas
> were being called for the password, as opposed to anything else in the
> dialog. Is there a sure-fire way to do this?
I tried patching the screen driver and watched for the proper bit
pattern of the real password characters, then replaced the bits with a
bullet pattern. I never did get that to work... ;-)
There are two main weaknesses of using a "bullet font" (or the StdText
method) to hide a password in a dialog box edittext item. First,
anyone can grab the password by choosing Copy from the Edit menu (under
Sys7). This is not an issue unless the user has a habit of typing a
password and leaving the dialog on the screen.
The more important drawback is that it is difficult to handle two-byte
character sets. Because the font would be script specific, extra
"bullet" characters would be emitted.
The source below solves the password-in-a-dialog problem by filtering
the event stream and modifying the proper key-down events. It keeps a
private copy of the password. Although this implementation does not
support multibyte character sets, it could be modified to do so easily
(and in fact I am going to have to do this eventually myself).
The PassFilter routine uses another dialog filter routine that handles
the non-password related stuff (OK and Cancel keyboard equivalents,
etc.) You need to write this y'self.
On a side note, I always liked the way the original StuffIt (I think)
handled the archive password. It just changed the font size to
something like 2, and used PICTs for the "static text" (there were no
non-password edit text items). Cute.
Mark.
- --------------------------------------------------------------------
"On the Internet, nobody knows you're a dog." Ice Peak Form Mice Elf
-- cartoon in New Yorker
/*
* (c)1994 Mark Valence
*
* Permission to use and alter this source is
* granted, provided that you do not transmit
* the resulting password in cleartext over a
* network (unless required by the protocol).
*/
#include <types.h>
#include <memory.h>
#include <events.h>
#include <windows.h>
#include <dialogs.h>
#include <controls.h>
/*
* example of usage:
*
* PassData pdata;
* Str255 mypass;
*
* ...
* pdata.passitem = MY_PASSWORD_ITEM;
* pdata.passmax = 8;
* pdata.bullet = '*';
* pdata.password = mypass;
* *mypass = 0;
* SetWRefCon(dialog, (long)&pdata);
* ModalDialog((ProcPtr)PassFilter, &item);
* ...
*/
/*
* a pointer to this structure is placed in the refCon
* of the dialog box that contains the password item.
* the buffer that 'password' points to must be at
* least 'passmax'+1 bytes (one byte for the length),
* and must initially be zero-length.
*/
typedef struct t_passdata {
short passitem; /* dialog item number of password text */
short passmax; /* maximum length of password */
char bullet; /* special character to use */
StringPtr password; /* pointer to a buffer for the real password */
} PassData;
/*
* this routine must be linked in from another source
* it is responsible for handling special keystrokes
* such as <return>, <enter>, <escape>, Cmd-., etc.
* UpdtFilter also handles window update events for
* application windows and the Edit menu command keys.
*/
pascal Boolean UpdtFilter (DialogPtr dialog, EventRecord *event, short
*item);
/*
* these routines are included below for completeness
*/
char *pstrdel (unsigned char *s, int ix, int len);
char *pstrins (unsigned char *s, unsigned char c, int ix);
pascal Boolean
PassFilter (DialogPtr dialog, EventRecord *event, short *item)
{
PassData *passp;
short selStart, selEnd;
unsigned char ch;
Str255 hold;
short kind;
Handle h;
Rect r;
/* take care of return, enter, cmd-.,
* escape, updates, Edit menu, etc.
*/
if (UpdtFilter(dialog, event, item))
return(true);
passp = (PassData *)GetWRefCon(dialog);
if (!(event->modifiers & cmdKey)
&& (event->what == keyDown || event->what == autoKey)
&& (((DialogPeek)dialog)->editField == (passp->passitem - 1)))
{
ch = event->message & charCodeMask;
selStart = (**(((DialogPeek)dialog)->textH)).selStart;
selEnd = (**(((DialogPeek)dialog)->textH)).selEnd;
switch (ch) {
case 0x08: /* backspace */
if (selEnd != selStart)
pstrdel(passp->password, selStart + 1, selEnd - selStart);
else if (selStart > 0)
pstrdel(passp->password, selStart, 1);
break;
case 0x09: /* tab */
case 0x1C: /* left arrow */
case 0x1D: /* right arrow */
case 0x1E: /* up arrow */
case 0x1F: /* down arrow */
break;
default:
BlockMove(passp->password, hold, sizeof(hold));
pstrdel(hold, selStart + 1, selEnd - selStart);
pstrins(hold, ch, selStart + 1);
if (*hold > passp->passmax) {
event->what = nullEvent;
SysBeep(1);
} else {
BlockMove(hold, passp->password, *hold + 1);
event->message &= 0xFFFFFF00;
event->message |= passp->bullet;
}
break;
}
GetDItem(dialog, ok, &kind, &h, &r);
HiliteControl((ControlHandle)h, (*passp->password ? 0 : 255));
}
return(false);
}
char *
pstrdel (unsigned char *s, int ix, int len)
{
int last;
if (len == 0 || ix > *s)
return(s);
last = ix + len;
if (last > *s) {
*s = ix - 1;
} else {
BlockMove(&s[last], &s[ix], *s - last + 1);
*s -= len;
}
return(s);
}
char *
pstrins (unsigned char *s, unsigned char c, int ix)
{
if (*s < 0x00FF)
(*s)++;
BlockMove(&s[ix], &s[ix + 1], *s - ix);
s[ix] = c;
return(s);
}
+++++++++++++++++++++++++++
>From kjohnso@nyx10.cs.du.edu (Kai)
Date: Fri, 4 Mar 94 21:26:04 GMT
Organization: Nyx, Public Access Unix at U. of Denver Math/CS dept.
In article <2klgi3$36o@dartvax.dartmouth.edu>,
kurash@dartmouth.edu <Mark.R.Valence@dartmouth.edu> wrote:
>In article <Jim.Matthews-250294091049@ishmael.dartmouth.edu>
>Jim.Matthews@dartmouth.edu (Jim Matthews) writes:
>
>There are two main weaknesses of using a "bullet font" (or the StdText
>method) to hide a password in a dialog box edittext item. First,
>anyone can grab the password by choosing Copy from the Edit menu (under
>Sys7). This is not an issue unless the user has a habit of typing a
>password and leaving the dialog on the screen.
>
>The more important drawback is that it is difficult to handle two-byte
>character sets. Because the font would be script specific, extra
>"bullet" characters would be emitted.
>
>The source below solves the password-in-a-dialog problem by filtering
>the event stream and modifying the proper key-down events. It keeps a
>private copy of the password. Although this implementation does not
>support multibyte character sets, it could be modified to do so easily
>(and in fact I am going to have to do this eventually myself).
>
>[source deleted...]
You can do the same trick and support all the standard TextEdit things
by putting a hidden TE item offscreen and rerouting key events to it.
Just keep the selections in the two items in sync, and match the number
of bullets in the visible item to the hidden one.
The user can copy the password all they want, but they just get bullets.
I think this is how the sample code in the H/I notes from Apple works...
Oh, if you're doing passwords, you should have a look at the note about
them, there are some standard ways for handling all the clicks and key
presses.
I can probably find both the H/I note and the sample code if you but me
about it.
-Kai
+++++++++++++++++++++++++++
>From moofster@world.std.com (A Happy Dog-Cow)
Date: Sun, 6 Mar 1994 05:36:58 GMT
Organization: The Nest of the Moofster
Sheesh! All of this talk of patching traps & weirdo fonts to just make
a password entry screen! Programmers should be on guard against
innapropriate over-engineering!! Sheesh! Just make a ModalDialogFIlter
procedure, intercept the update routine for the item(s) in question,
and voila. Patching traps or coming up with exotic fonts to perform
this is unnecessary!
Robert M. Seretny, Armesti Research,
(Macintosh/SCSI guru for short-term hire; email moofster@world.std.com)
+++++++++++++++++++++++++++
>From danprice@delphi.com
Date: Mon, 7 Mar 94 18:55:47 -0500
Organization: Delphi (info@delphi.com email, 800-695-4005 voice)
I dunno, I wrote a short routine for a friend in a comp/sci course who wanted
to impress his teacher. Basically, I set up a dialog with 12 buttons, in
a numeric keypad arrangement. The things that's neat about this is that,
unless the "hacker" is extremely clever, he won't be able to use a filter
(sorry, not a filter) a trap patch to intercept the passcode, as the
difficulty of figuring which part of the screen clicked is fairly high.
Also, I thought about randomly scrambling the buttons in the dialog, to
make this _even_ harder, as well as to foil those with binoculars and such.
I think this whole password thing is overkill....
-dp
---------------------------
>From python@jhunix.hcf.jhu.edu (Bryan Arntson)
Subject: Permanent front windows...
Date: 3 Mar 1994 17:53:33 -0500
Organization: Homewood Academic Computing, Johns Hopkins University, Baltimore, Md, USA
I apologize for not knowing what these windows are called, but how do I
create those windows that are ALWAYS in the front. They look like little
fake windows. They have B&W window titles, that are about 10 pixels high,
and then the window below them. What are these called? And most
importantly, HOW DO I CREATE ONE? Could someone post, or send me, a short
code on the subject?
Thanks in advance,
Bryan
python@jhunix.hcf.jhu.edu
+++++++++++++++++++++++++++
>From troy@i-link.com (Troy Gaul)
Date: 3 Mar 1994 23:24:53 -0600
Organization: I-Link, Ltd., Des Moines, IA
In article <2l5ppdINN5qk@jhunix.hcf.jhu.edu>,
Bryan Arntson <python@jhunix.hcf.jhu.edu> wrote:
>I apologize for not knowing what these windows are called, but how do I
>create those windows that are ALWAYS in the front.
There are several names that are used, including 'Utility Window', 'Tool
Window', 'Palette', 'Windoid', 'Floating Window', and 'Floater'.
>They look like little
>fake windows. They have B&W window titles, that are about 10 pixels high,
>and then the window below them.
They don't _have_ to have a B&W window title. The only reason that I can
think of that many of them are B&W is that the programmers didn't know
about the Infinity Windoid WDEF (which, it happens, I wrote), which gives
you a System 7-style coloring scheme (but is also compatible with System 6).
It gives these to you for free, as it is freeware, and worry-free (it's been
well tested, and the source is included).
>What are these called? And most
>importantly, HOW DO I CREATE ONE? Could someone post, or send me, a short
>code on the subject?
You can make a window with this type of a titlebar by getting the Infinity
Windoid WDEF from the anonymous FTP site:
ftp://ftp.i-link.com/pub/infsys/
This WDEF does not help you make the window float on top of the others,
however. To do this, you need a floating window library. There was one
included with Develop 15, and updated code was included with Develop 16.
You can pick up the latest version of that code, along with the text of
the article (through an arrangement I make with Apple), in the same place.
_troy
--
//////// ////// Troy Gaul t-gaul@i-link.com //
// // I-Link, Ltd. //
// // // "Iungo ergo sum." (I-Link, therefore I am.) //
// ////// __________________________________________________________ //
+++++++++++++++++++++++++++
>From kurisuto@chopin.udel.edu (Sean J. Crist)
Date: 4 Mar 1994 11:37:41 -0500
Organization: University of Delaware
>This WDEF does not help you make the window float on top of the others,
>however. To do this, you need a floating window library. There was one
>included with Develop 15, and updated code was included with Develop 16.
>You can pick up the latest version of that code, along with the text of
>the article (through an arrangement I make with Apple), in the same place.
Or, for that matter, you could just write your own routines to do this.
This only took me a few hours to do. Basically, you've got to rewrite the
top level of the window manager. A good start is to write a routine that
acts like SelectWindow (calling ShowHide and HiliteWindow) except that it
leaves your Palette window in front. Then go through your code and do a
global search-and-replace to change SelectWindow to the name of your
replacement routine. If you can get that much working properly, that's
90% of the game.
If there's interest, I can post my code; it's pretty complicated, though,
because I'm doing a lot more than just supporting floating palettes.
Rather than keep a million WindowPtr's to everything (which is messy when
your application allows the user to open any number of instances of a
particular type of window), I keep information about the window in a
handle stored in the window's RefCon. Then when I need window number X of
type Y, I call one of my routines to quickly search through the linked
list of windows to try to find a match. I can clean up this code a little
and post it if there's interest.
--Sean (kurisuto@chopin.udel.edu)
\/ __ __ _\_ | If restaurants were named as gay organizations are,
--- | | \ / | "McDonald's" would be called "Meat, Bread, Vegetables,
_| ,| ,| ----- | Beverages, Condiments, and Friends" (MBVBCF for short).
_| ,| ,| [_] |--------------------------------------------------------
| | | [_] | Finger this account for a copy of the Bill of Rights.
---------------------------
>From andersw@hum.gu.se (Anders Wahlin)
Subject: Preference file question!
Date: Fri, 4 Mar 1994 08:03:28 GMT
Organization: Hum Fak:s Dataservice
Almost every program has a preference file. I have twoo very simple
questions about this.
1% Is it "wrong" to have a resource file as a preference file?
2% How can I create an icon on my preference file, within the program?
Thanks!
--
Anders Wahlin
andersw@hum.gu.se
+++++++++++++++++++++++++++
>From rmah@panix.com (Robert S. Mah)
Date: Fri, 04 Mar 1994 04:52:40 -0500
Organization: One Step Beyond
andersw@hum.gu.se (Anders Wahlin) wrote:
> Almost every program has a preference file. I have twoo very simple
> questions about this.
>
> 1 Is it "wrong" to have a resource file as a preference file?
No, many programs use resources to store their prefs. The only drawback is
that the file is no longer platform independent. I've often thought of
using a text file to store prefs.
> 2 How can I create an icon on my preference file, within the program?
Simply add an entry into your BNDL resource with associated FREF and
ICN#/icl/ics resources.
However, please think about using the standard 'pref' file type. The
finder will give it a nice prefs style icon and people's preferences folder
will open just a bit faster. Now if everyone did this...
Cheers,
Rob
________________________________________________________________________
Robert S. Mah One Step Beyond rmah@panix.com
+++++++++++++++++++++++++++
>From Lars.Farm@nts.mh.se (Lars Farm)
Date: Fri, 04 Mar 1994 11:33:02 +0100
Organization: Mid Sweden University
In article <andersw-040394090400@bigmac.hds.gu.se>, andersw@hum.gu.se
(Anders Wahlin) wrote:
> 1% Is it "wrong" to have a resource file as a preference file?
No. It's common practice.
> 2% How can I create an icon on my preference file, within the program?
Set the file type to 'pref'.
Lars
--
Lars.Farm@nts.mh.se
+++++++++++++++++++++++++++
>From peter@ncrpda.curtin.edu.au (Peter N Lewis)
Date: 5 Mar 1994 21:14:20 +0800
Organization: NCRPDA, Curtin University
rmah@panix.com (Robert S. Mah) writes:
>However, please think about using the standard 'pref' file type. The
>finder will give it a nice prefs style icon and people's preferences folder
>will open just a bit faster. Now if everyone did this...
Do this - it's much nicer. I used to do it the other way with a BNDL and
icon for the prefs file, but the Preferences folder is full up with
thousands of different icons, it's just a mess. So use the 'pref' file
type, and don't worry about designing an icon, and life will be good.
Peter.
--
Peter N Lewis <peter.lewis@info.curtin.edu.au> Ph: +61 9 368 2055
+++++++++++++++++++++++++++
>From perm@csd.uu.se (Per Mildner)
Date: 11 Mar 1994 14:56:23 GMT
Organization: Computing Science Dept.,Uppsala University, Sweden
Several people have suggested using the 'pref' file type for
preference files. There is one problem with this, this is the type
for the finder prefs. Most people thinks this is a good thing as this
automagically gives the pref file a good icon, but the people
suggesting this are not likely to use balloon help in the finder :-)
If you use the pref file you better add some balloon info in your pref
file too. (Another potential problem might be with EasyOpen or
whatever which I have not used).
Regards,
--
Per Mildner Per.Mildner@CSD.UU.SE
Computing Science Dept. tel: +46 18 181049
Uppsala University, Sweden fax: +46 18 521270
+++++++++++++++++++++++++++
>From t-gaul@i-link.com (Troy Gaul)
Date: Fri, 11 Mar 1994 12:35:25 -0600
Organization: I-Link, Ltd.
In article <PERM.94Mar11155623@groucho.csd.uu.se>, perm@csd.uu.se (Per
Mildner) wrote:
> Several people have suggested using the 'pref' file type for
> preference files. There is one problem with this, this is the type
> for the finder prefs. Most people thinks this is a good thing as this
> automagically gives the pref file a good icon, but the people
> suggesting this are not likely to use balloon help in the finder :-)
> If you use the pref file you better add some balloon info in your pref
> file too.
I really don't think this is a big issue against using that as a file type.
Besides, I have several other pieces of Apple software (the Apple Modem
Tool was the one I saw when I checked this out) that also do the same
thing.
> (Another potential problem might be with EasyOpen or
> whatever which I have not used).
I don't see where this would be a problem. Actually, quite the opposite is
true. If you have the resources for Easy Open in your application, then you
can describe the preferences file with a 'kind' resource as 'MyApplication
preferences', and this would appear in the Finder names lists of the
preferences folder (or the get info box).
Easy Open uses the creator of the file to determine its labeling,
apparently, the Balloon help in the Finder doesn't look at the creator of
the file when the cursor's pointed at a 'pref' file as it should.
I've taken the advice to use 'pref' as the file type and to NOT include an
icon for that type to heart. I'm doing it in most of my own programming
projects now.
_troy
//////// //////___Troy Gaul_________________________t-gaul@i-link.com__ //
// // I-Link, Ltd. ; West Des Moines, Iowa //
// // // "Iungo ergo sum." (I-Link, therefore I am.) //
// //////________________________________________________________ //
---------------------------
>From pope@imv.aau.dk (Povl H. Pedersen)
Subject: Reading PICT files != 72 dpi. How ?
Date: 26 Feb 1994 16:01:21 GMT
Organization: Information and Media Science, Aarhus University, DENMARK
I am working on a small custom image modifying program, and it will have
to load in PICT files created in other applications.
I have managed to steal some code that will rwad/write PICT files, but my
problem now is, that the end user somethimes generates PICTs in a better
resolution than 72 dpi. When he reads them in, they are shrinked to keep
size as the original, and he then loses information.
How do I read in PICT files with all osrts of resolution, handle them as
pixel-by-pixel images, and then finally write them back with their
original resolution info ?
thanks in advance,
- -
Povl H. Pedersen - Macintosh Consultant and Programmer
pope@imv.aau.dk (preferred) / povlphp@uts.uni-c.dk
"Macintosh...for those who can see through Windows!"
+++++++++++++++++++++++++++
>From pope@imv.aau.dk (Povl H. Pedersen)
Date: 28 Feb 1994 18:16:17 GMT
Organization: Information and Media Science, Aarhus University, DENMARK
I wanted to know how I could read in a PICT in a higher than 72dpi
resolution, and keep every single pixel. I tried the net, as it is usual
a good fast reference manual ;^)
The net did not want to answer me, so I did spend some time, and found a
working way. I am using information on page 17-24 of Inside Macintosh
volume VI. This info is not documented in any headers anywhere, but I
suppose it is safe to use.
(Now, why has Apple not given us routines to read/write PICT files ? They
should be a natural part of the toolbox. Just like some way to get a
PicHandle from a pixmap).
My ugly code is enclosed below. I did slight editing after copy/pasting, so
it may contain a few syntax errors. My routine allocates a new offscreen
GWorld, and reads the picture in here. Only minimum level of error
checking is done. The application where this is used will not be run on
large images on machines with less than 32-64 MB RAM. So memory is no
problem. This is one reason I make the offscreen pixmap 32 bits instead
of using the information from the file. Another reason is, that I parse
all pixels in a loop that expects 32bit pixmap.
Disclaimer: This code is guaranteed to be incompatible with at least one
version of one Microsoft product. Not necesarily now, but then in the
future. Don't blame me. Blame the guilty ones.
Povl
- -----------------------------
// structure not defined anywhere. Contents just listed in IM VI, page 17-24
typedef struct {
unsigned short picSize;
Rect picFrame;
// Now comes the header as displayed in IM VI, but not defined in any headers
short s1; // = 0x0011 for special resolution
short s2; // = 0x02FF
short HeaderOp; // Opcode for PICT command. 0x0C00 = header
short version; // = -2 for extended version 2 pict file
short reserved;
Fixed hRes; // horizontal resolution
Fixed vRes; // vertical resolution
Rect srcRect; // Native source rectangle
// More stuff follows but is ignored
} myVersion2PICTHeaderT;
static short gPICT_FILE_RESNUM;
// Quickdraw bottleneck routine to do the hard work
pascal void GetPICTData( Ptr dataPtr, short byteCount )
{
long longCount;
longCount = byteCount;
err = FSRead( gPICT_FILE_RESNUM, &longCount, dataPtr );
}
// This routine takes the following parametres:
// p: a pointer to a GWorldPtr. On exit it will point to a new GWorld.
// filespec: FSSpec pointer that identifies the PICT file to read.
void getPICTFile( GWorldPtr *p, FSSpec *fileSpec)
{
QDProcsPtr savedProcs;
CQDProcs myProcs;
GDHandle gdh;
CGrafPtr port;
PicHandle thePic = nil;
long longCount;
short h, w;
Rect r,gr;
PictInfo pinfo;
Fixed vRes, hRes; // horizontal/vertical resolutions
myVersion2PICTHeaderT myPICTheader;
*p = nil; // lazy way to return error
// Open file and skip old MacPaint header
err = FSpOpenDF( fileSpec, fsRdPerm, &gPICT_FILE_RESNUM );
SetFPos( gPICT_FILE_RESNUM, fsFromStart, 512); // skip header
// clear my header.
memset( &myPICTheader, 0, sizeof(myPICTheader) );
// Get the IM VI documented header
longCount = sizeof( myPICTheader );
err = FSRead( gPICT_FILE_RESNUM, &longCount, &myPICTheader );
if (err != noErr) {
TellUser( "Unpected End-of-File. Replace user and try again");
return;
}
// Test if we have an extendended version 2 pict header
if ( myPICTheader.s1 == 0x0011 && myPICTheader.s2 == 0x02FF &&
myPICTheader.HeaderOp == 0x0C00 && myPICTheader.version == -2) {
// Now we have a PICTure of another resolution
hRes = myPICTheader.hRes;
vRes = myPICTheader.vRes;
}
else
hRes = vRes = Long2Fix( 72 ); // default resolution
// skip back to header again, loading pict should start at pos=512
SetFPos( gPICT_FILE_RESNUM, fsFromStart, 512);
// Get room for the real header and read it
thePic = (PicHandle) NewHandle(sizeof(Picture));
longCount = sizeof( Picture );
FSRead( gPICT_FILE_RESNUM, &longCount, (Ptr) *thePic );
// different resolution, use the info from our version 2 extended header
if (hRes != Long2Fix( 72 )) {
w = myPICTheader.srcRect.right - myPICTheader.srcRect.left;
h = myPICTheader.srcRect.bottom - myPICTheader.srcRect.top;
r = myPICTheader.srcRect;
}
else { // just use the data the old way
w = (**thePic).picFrame.right;
h = (**thePic).picFrame.bottom;
r = (**thePic).picFrame;
}
// Now that we have the header, we know which size to make our offscreen buffer
GetGWorld( &port, &gdh );
SetRect( &gr, 0, 0, w, h );
err = NewGWorld( p, 32, &gr, (CTabHandle) 0, (GDHandle) 0, 0 );
if (err != noErr)
DoCrashTheMachineAndAnnoyTheEndUser();
SetGWorld( *p, nil );
// Set our resolution. This makes sure the usual save routine will
// write it back for whatever DPI we use.
(*p->portPixMap)->vRes = vRes;
(*p->portPixMap)->hRes = hRes;
// SetStdCProcs
SetStdCProcs( &myProcs );
myProcs.getPicProc = GetPICTData;
savedProcs = ((GrafPtr) p)->grafProcs;
((CGrafPtr) p)->grafProcs = &myProcs;
// this line does the real work
DrawPicture( thePic, &r );
SetGWorld( port, gdh );
FSClose( gPICT_FILE_RESNUM );
DisposHandle( (Handle) thePic );
((GrafPtr) p)->grafProcs = savedProcs;
}
- -
Povl H. Pedersen - Macintosh Consultant and Programmer (For hire).
System Administrator at the Aarhus Engineering School
pope@imv.aau.dk (preferred) / povlphp@uts.uni-c.dk
"Macintosh...for those who can see through Windows!"
---------------------------
>From temple@itd.nrl.navy.mil (Dr. Jon Gerard Temple)
Subject: Resources on PowerPC
Date: Fri, 11 Mar 1994 19:56:23 GMT
Organization: Naval Research Laboratory
There is an issue I have a little trouble with: it is my understanding
that Native applications on the Power Macintosh will not use resources
(or the resource fork.). What does this mean for programmers that are
used to ResEdit for creating/editing resources, whose code points to
reusable resources, etc? Will this feature of Mac programming simply
cease to exist when writing Native RISC applications or is there an
alternative approach that will treat part of the DATA fork on PPC Macs
as editable, callable, reusable resources that a new version of ResEdit
(DataEdit??) will able to work with?
Ideas?
+++++++++++++++++++++++++++
>From minnis@cobaf.unt.edu (Minnis, Robert)
Date: Fri, 11 Mar 1994 20:15:23 GMT
Organization: College of Business Administration, UNT
In article <CMInE0.5nM@ra.nrl.navy.mil> temple@itd.nrl.navy.mil (Dr. Jon Gerard Temple) writes:
>From: temple@itd.nrl.navy.mil (Dr. Jon Gerard Temple)
>Subject: Resources on PowerPC
>Date: Fri, 11 Mar 1994 19:56:23 GMT
>There is an issue I have a little trouble with: it is my understanding
>that Native applications on the Power Macintosh will not use resources
>(or the resource fork.). What does this mean for programmers that are
>used to ResEdit for creating/editing resources, whose code points to
>reusable resources, etc? Will this feature of Mac programming simply
>cease to exist when writing Native RISC applications or is there an
>alternative approach that will treat part of the DATA fork on PPC Macs
>as editable, callable, reusable resources that a new version of ResEdit
>(DataEdit??) will able to work with?
>Ideas?
>From what I understand, resources are not going to vanish. PPC code will be
stored in the data fork (68K code will still be stored in CODE resources).
Robert Minnis
+++++++++++++++++++++++++++
>From peirce@outpost.SF-Bay.org (Michael Peirce)
Date: Fri, 11 Mar 94 15:39:49 PST
Organization: Peirce Software, Inc.
In article <CMInE0.5nM@ra.nrl.navy.mil> (comp.sys.mac.programmer), temple@itd.nrl.navy.mil (Dr. Jon Gerard Temple) writes:
> There is an issue I have a little trouble with: it is my understanding
> that Native applications on the Power Macintosh will not use resources
> (or the resource fork.). What does this mean for programmers that are
> used to ResEdit for creating/editing resources, whose code points to
> reusable resources, etc? Will this feature of Mac programming simply
> cease to exist when writing Native RISC applications or is there an
> alternative approach that will treat part of the DATA fork on PPC Macs
> as editable, callable, reusable resources that a new version of ResEdit
> (DataEdit??) will able to work with?
Resourse do *not* go away on the Power Mac. PowerPC executable code
is not found in CODE resources (though it can be found in a few special
code resources) rather in the data fork. Still, all other "normal"
Mac resources are still around and used. In fact, CODE resource can
still contain 68K code - this is how you implement fat binaries.
So relax, ResEdit isn't going away.
-- Michael Peirce -- peirce@outpost.sf-bay.org
-- Peirce Software, Inc. -- 719 Hibiscus Place, Suite 301
-- -- San Jose, California USA 95117
-- Makers of: Smoothie & -- voice: +1.408.244.6554 fax: +1.408.244.6882
-- Peirce Print Tools -- AppleLink: peirce & America Online: AFC Peirce
+++++++++++++++++++++++++++
>From richardb@cocytus.demon.co.uk (Richard Buckle)
Date: Sat, 12 Mar 1994 12:57:25 GMT
Organization: None
In article <CNjbKKKX.qcga43@outpost.SF-Bay.org> peirce@outpost.SF-Bay.org
(Michael Peirce) writes:
>
>...
>Resourse do *not* go away on the Power Mac. PowerPC executable code
>is not found in CODE resources (though it can be found in a few special
>code resources) rather in the data fork. Still, all other "normal"
>Mac resources are still around and used. In fact, CODE resource can
>still contain 68K code - this is how you implement fat binaries.
>...
Arrgggh! How could Apple do this to me? I need my data forks for DATA.
A major part of my job is writing computationally *very* intensive XCMDs (for
HyperCard) and CODE resources (for Excel). These are of course stored in the
resource forks of stacks and spreadsheets and we need to turn them into fat
binaries. And HyperCard and Excel expect to call CODE and XCMD resources, not
any other type.
Will it be possible to have 68K stub resources call 'special' PowerPC
executable resources?
If not, I guess I shall have to store the PowerPC code in the data fork of
another file. As new releases are very frequent this would be an installation
nightmare. Would the new Shared Library Manager help at all?
BTW, how is the global A4 addressing issue handled in PowerPC standalone code?
Replies by mail please -- I shan't have time to read much news next week. I
shall summarise in c.s.m.p when the shouting is over.
Apologies if these are RTFM-type questions -- we have not yet taken delivery of
CodeWarrior so I am rather in the dark.
- -
Richard Buckle
richardb@cocytus.demon.co.uk
richardb@cix.compulink.co.uk
+++++++++++++++++++++++++++
>From wdh@netcom.com (Bill Hofmann)
Date: Sat, 12 Mar 1994 20:00:40 GMT
Organization: NETCOM On-line Communication Services (408 241-9760 guest)
richardb@cocytus.demon.co.uk (Richard Buckle) writes:
>A major part of my job is writing computationally *very* intensive XCMDs (for
>HyperCard) and CODE resources (for Excel). These are of course stored in the
>resource forks of stacks and spreadsheets and we need to turn them into fat
>binaries. And HyperCard and Excel expect to call CODE and XCMD resources, not
>any other type.
This seems to be enough of a FAQ that I've responded here as well as directly.
Michael misspoke himself slightly: BY DEFAULT, PowerPC code for APPLICATIONS
lives in the data fork of the file. What this means is:
* PPC application code can be in the data fork
* PPC application code can be in one huge resource
You just have to set up the (mandatory) 'cfrg' resource properly.
Also:
* standalone code resource can be all 680x0
* standalone code resources can be all PowerPC
* standalone code resources can be "fat", containing both
If standalone code will only be called from 680x0 code,
* it can be plain vanilla 680x0 code, like today
* it can be PPC code with a "RoutineDescriptor" at the front
* it can be "fat" with a "RoutineDescriptor" at the front
680x0 code doesn't need to know about the PowerPC AT ALL.
If standalone code will only be called from PowerPC code,
* it can be naked PPC code
* it can be PPC code with a RoutineDescriptor
* it can be 680x0 code with a RoutineDescriptor
* it can be "fat" with a RoutineDescriptor
* it can be naked 680x0 code
In all but the FIRST (native PPC), it must be called using a special routine.
So if you write PPC-aware code, you need to read the MixedMode manager
chapter of the Mac on RISC SDK.
If standalone code may be called from either 680x0 or PPC:
* it can be naked 680x0 code
* it can be PPC code with a RoutineDescriptor
* it can be 680x0 code with a Routine Descriptor
* it can be "fat" with a RoutineDescriptor
Since not all of the ToolBox and OS are native, ANY standard code resource
that contains PPC code MUST have a routine descriptor. That goes for things
like XCMDs as well.
I think that about covers it. Whoever maintains the FAQ might want to
put this in there.
Oh yes, Apple Developer University is offering a course called "PowerPC
Boot Camp", which covers this and lots more. It's a four day course,
with plenty of hands-on, including code resource kinda stuff. I'm one
of the Drill Sargeants, oops, instructors, so, I have an ulterior motive.
--
-Bill Hofmann wdh@netcom.COM
Fresh Software and Instructional Design +1 510 524 0852
+++++++++++++++++++++++++++
>From Mark_Day@powertalk.apple.com (Mark Day)
Date: Sat, 12 Mar 1994 00:11:42 GMT
Organization: Apple Computer, Inc.
In article <CMInE0.5nM@ra.nrl.navy.mil>, temple@itd.nrl.navy.mil (Dr. Jon
Gerard Temple) wrote:
> There is an issue I have a little trouble with: it is my understanding
> that Native applications on the Power Macintosh will not use resources
> (or the resource fork.). What does this mean for programmers that are
> used to ResEdit for creating/editing resources, whose code points to
> reusable resources, etc? Will this feature of Mac programming simply
> cease to exist when writing Native RISC applications or is there an
> alternative approach that will treat part of the DATA fork on PPC Macs
> as editable, callable, reusable resources that a new version of ResEdit
> (DataEdit??) will able to work with?
>
> Ideas?
The code for native applications is normally found in the data fork,
not a bunch of CODE resources (for non-native code). You can (and
should) still use resources. In fact, you can have a "fat" application
with both CODE resources and native code in the data fork, that share
other non-code resources (like strings, icons, etc.). Such "fat"
applications will execute the native code on Power Macintosh or the
old 68K CODE resources on non-Power Macintoshes.
--
Mark Day, Apple Computer, Inc.
mday@apple.com
---------------------------
>From neeri@iis.ee.ethz.ch (Matthias Neeracher)
Subject: Safer Segments ?
Date: 15 Mar 94 16:49:06
Organization: Integrated Systems Laboratory, ETH, Zurich
My program usually has multiple resource files open, some of which contain CODE
resources (they are similar to AppleScript droplets). Unfortunately, if
_LoadSeg is called while one of the other CODE containing resource forks is
in front of the resource chain, a nasty crash results. So far, I have been able
to work around this problem by calling UseResFile() in all the right places,
but I'd prefer to know a simpler solution, if one exists.
Any ideas?
Matthias
- ---
Matthias Neeracher neeri@iis.ee.ethz.ch
"I really don't want the SNMP agent controlling my toilet to tell
someone when/where I'm using it." -- Sean Graham
+++++++++++++++++++++++++++
>From wysocki@netcom.com (Chris Wysocki)
Date: Wed, 16 Mar 1994 10:02:35 GMT
Organization: Global Village Communication, Mountain View, CA
In article <NEERI.94Mar15164906@yggdrasil.ethz.ch> neeri@iis.ee.ethz.ch (Matthias Neeracher) writes:
>My program usually has multiple resource files open, some of which contain CODE
>resources (they are similar to AppleScript droplets). Unfortunately, if
>_LoadSeg is called while one of the other CODE containing resource forks is
>in front of the resource chain, a nasty crash results. So far, I have been able
>to work around this problem by calling UseResFile() in all the right places,
>but I'd prefer to know a simpler solution, if one exists.
It's hardly simple, but the most robust thing to do is to patch
_LoadSeg and have your patch set the current resource file, call the
"real" _LoadSeg and restore the previous resource file on the way out.
Patching _LoadSeg also allows you to preflight the loading of the code
resources so that you can avoid crashing in the event that the Segment
Loader can't load the segment. I've use this technique in a number of
applications and it works quite well; if you have MacApp 3.x, take a
look at UMemory.cp and UMemory.a to see how it can be done.
Chris.
+++++++++++++++++++++++++++
>From Greg_Marriott@genmagic.com (Greg Marriott)
Date: Thu, 17 Mar 1994 02:26:31 -0800
Organization: General Magic, Inc.
neeri@iis.ee.ethz.ch (Matthias Neeracher) wrote:
> [...] if _LoadSeg is called while one of the other CODE
> containing resource forks is in front of the resource chain, a nasty
> crash results. So far, I have been able to work around this problem
> by calling UseResFile() in all the right places, [...]
>
> Any ideas?
I don't know if you'll think this is simpler or not... You might try
patching _LoadSeg to call UseResFile() before jumping to the original code.
--
Greg Marriott
Just Some Guy
General Magic, Inc.
Disclaimer: My opinions are not necessarily the same as General Magic's.
(can a company even HAVE an opinion?)
+++++++++++++++++++++++++++
>From ari@world.std.com (Ari I Halberstadt)
Date: Thu, 17 Mar 1994 21:08:39 GMT
Organization: The World Public Access UNIX, Brookline, MA
In article <NEERI.94Mar15164906@yggdrasil.ethz.ch>,
Matthias Neeracher <neeri@iis.ee.ethz.ch> wrote:
>My program usually has multiple resource files open, some of which contain CODE
>resources (they are similar to AppleScript droplets). Unfortunately, if
>_LoadSeg is called while one of the other CODE containing resource forks is
>in front of the resource chain, a nasty crash results. So far, I have been able
>to work around this problem by calling UseResFile() in all the right places,
>but I'd prefer to know a simpler solution, if one exists.
You can patch the _LoadSeg trap. Here's the code I use to patch
LoadSeg. It checks that there's enough memory available before loading
the segment. If you add a call to UseResFile just before and after the
GetResource call it should do what you need. The PatchType structure
contains info about the patch that you'd set when installing the
patch, though you could just use some global variable to hold the
address of the routine returned by NGetTrapAddress.
/* data needed by a patch */
typedef struct PatchType {
struct PatchType *next; /* next patch */
pascal void (*addr)(...); /* address of patch routine */
pascal void (*trap)(...); /* saved trap address */
TrapType type; /* type of trap */
short num; /* number of trap */
Boolean installed; /* true if patch was installed */
} PatchType, *PatchPtr, **PatchHandle;
/* The PATCH_ENTER macro should be the first executable statement in
your patch routine. PATCH_ENTER saves all of the registers and sets
up register a5. PATCH_ENTER also ensures that the routine has a stack
frame so that the PATCH_RETURN macro can be used. */
#define PATCH_ENTER() \
{ long _patch_force_stack_frame; { /* force stack frame of at least 4 bytes */ \
asm { movem.l a0-a5/d0-d7, -(sp) } /* save registers */ \
asm { move.l #0x0904, a5 } /* setup register a5 */ \
asm { move.l (a5), a5 }
// this PATCH_RETURN macro magically restores registers d0-d7/d0-a7 to the
// same values they had when it was entered, which makes it a pretty
// safe way to patch traps (note: well, i've only been using this code
// for about a week, but i stepped through it and it should work).
/* The PATCH_RETURN macro jumps to the address of the originally patched
routine. You should call PATCH_RETURN at the end of your patch. The
'patch' parameter should be a pointer returned from PatchBegin. The
compiler must generate a stack frame (using register a6) for the patch
routine. This should be ensured by the PATCH_ENTER macro. */
#define PATCH_RETURN(patch) \
} } \
{ \
asm { move.l a6, a1 } /* get current value of a6 */ \
asm { move.l (a6), -(a6) } /* shift location of saved a6 */ \
asm { move.l patch, a0 } /* get pointer to patch record */ \
asm { move.l PatchType.trap(a0), (a1) } /* put patched routine's address on stack */ \
asm { movem.l (sp)+, a0-a5/d0-d7 } /* restore registers */ \
asm { unlk a6 } /* pop stack frame */ \
asm { rts } /* return to patched routine */ \
}
static PatchType *gPatchLoadSeg; /* data about patch */
/* get a code resource */
static Handle GetCodeResource(ResID id)
{
Handle code;
require(LMGetResLoad());
SetResLoad(false);
code = GetResource('CODE', id);
SetResLoad(true);
FailNILRes(code);
/* We use MemAvailableNoCushion since MemAvailable could unload
segments, and if segments are unloaded from within this patch
the program crashes. */
if (! *code && ! MemAvailableNoCushion(SizeResource(code)))
FailOSErr(memFullErr);
SetResAttrs(code, GetResAttrs(code) & ~resLocked);
FailResError();
LoadResource(code);
FailResError();
return(code);
}
/* For its own reasons, perhaps related to using FAR code, THINK C seems
to patch the _LoadSeg trap. THINK C also makes code resources locked.
Unfortunately, this prevents _LoadSeg from calling MoveHHi on segments,
even if the low-memory global SegHiEnable is non-zero. Having code
segments low in memory leads to severe heap fragmentation when pointers
are allocated above the code segments. This patch will load the resource,
move it to the top of the heap, and lock it there. This patch will also
trigger an exception if the resource couldn't be loaded or if there isn't
enough memory to load the resource. */
static pascal void PatchLoadSeg(ResID segnum)
{
Handle code;
PATCH_ENTER();
code = GetCodeResource(segnum);
if (code && LMGetSegHiEnable()) {
MoveHHi(code);
HLock(code);
}
PATCH_RETURN(gPatchLoadSeg);
}
// this has nothing to do with the above patch, but could be useful
// to someone who wants to load a segment
pascal void LoadSegTrap(ResID seg) = _LoadSeg;
/* load the segment */
static void LoadSeg(ResID seg)
{
asm {
move.w seg, -(sp)
bra.s @1 /* call LoadSeg */
bra.s @2 /* LoadSeg returns here */
nop /* fill up two bytes */
@1: LoadSegTrap
@2:
}
}
--
Ari Halberstadt ari@world.std.com #include <std/disclaimer.h>
"These beetles were long considered to be very rare because very few
entomologists look for beetles in the mountains, in winter, at night,
during snow storms." -- Purves W. K., et al, "Life: The Science of
---------------------------
>From mssmith@afterlife.ncsc.mil (M. Scott Smith)
Subject: Speeding up animation; questions
Date: Sun, 27 Feb 1994 23:49:11 GMT
Organization: The Great Beyond
Ramble alert! (This one's kinda long..)
Hi gang!
I found a few minutes this weekend to revisit my much-procrastinated
tour into the development of Mac arcade games.. (Well, I haven't really
procrastinated, I just haven't had the time. :(
I've been developing a direct-screen animation toolkit which I'll
(eventually) be using to write games. I'm now working on the "animation
engine" -- the heart of the game where all of the animation will be
performed.
What I'll do is describe the method(s) I'm thinking about using. Any
comments on my methods would be greatly appreciated; don't hesitate to
tell me that I'm going about it all the wrong way.
The type of game I'll be writing will probably be similar to Lemmings,
in that I need to have support for lots of (fairly small) sprites. Having
30 separate sprites on screen and moving is not too much to ask. (It may
be too much to program, but...) But they'll generally be 32x32 pixels or
smaller, with room for a few larger ones. I'll write this game to fill
the 12" monitor -- 512x384 pixels. It will only support color, probably
require System 7, etc. And it uses "direct-screen" drawing; filling the
video RAM with bytes for instant gratification.
First question: will direct-screen animation work on the PowerPC, if
the loosely-defined "correct" way of doing it is followed? From what I
have heard and seen of the PowerPC, it doesn't seem like there's any
inhibiting factors against using direct-screen graphics. But I haven't
gotten my hands on a PPC compiler yet to try it out.
Ok. So, here's how I'll do my animation: I'll have two buffers (at
about 384k each -- this game will probably require at least 2 megs) the
size of the game area. One of these buffers contains the background.
The other buffer is a "work" buffer. First I copy the entire background
to the work buffer. Then I mask or draw all of my sprites on top of the
background in the work buffer. Then I copy the work buffer to the screen.
The process continues for each frame of animation. I'll sync the drawing
with the electron beam, if necessary.
From previous discussions here and elsewhere, this seems to be an
accepted method that will result in flicker-free animation. It's memory-
intensive, but as I have described it, relatively easy to implement.
But (at least) two things bother me: there's two copies of 512x384 bytes
occurring for each frame of animation: first the copy of the background
into the work buffer, then the copy of the work buffer to the screen. Not
to mention all the copies of the sprites -- possibly up to 30.
I know there are probably ways to prevent copying the entire screen,
and I could use some suggestions. I could keep track of a "dirty rectangle"
that needs updating, but for my game I'll have sprites all over the screen
so it seems like I'll need to copy the whole screen anyway. Keeping a
list of rectangles needing to be copied is another possibility, but this
will result in a lot of overhead and required computations, and numerous
little copies that would probably make it slower.
I did some (rough) experimentation. I took two sprites, each 512x384,
and blasted them to the screen in alternating order for 30 seconds,
incrementing a counter with each blast. I did this on a Macintosh IIfx.
Here are the results:
No optimizations: 356 frames / 30 seconds or 11.87 frames/s
Compiled for 68020 and up,
with all Symantec C++ opts: 554 frames / 30 seconds or 18.47 frames/s
Comments: I used the Symantec C++ compiler. And keep in mind I'll
have at least two full copies going on for each frame, plus all the work
involved in drawing the numerous sprites, overhead from the rest of the
game's I/O and logic, etc. I don't think a bad prediction would be that
with those results, I might end up with around 6 frames per second. Isn't
that pretty bad? For arcade games, how many "complete" screen updates / s
are there usually? (I've also got to remind myself that I'm developing
this on a IIfx -- which (for now) is still speedier than the average Mac.)
Here's the code I use for blasting the 512x384 sprite to the screen:
void
Sprite::Plot(long x, long y)
{
long *longPtr, *longPtr2;
register long xx;
register long yy;
long sum1, sum2;
if (data_allocated == 1)
{
HLock(theData);
longPtr2 = (long *)(*theData);
sum1 = y + height;
sum2 = x + width;
for (yy=y; yy<sum1; yy++)
{
longPtr = (long *)(x + theScreen->line_ptr[yy]);
for (xx=x; xx<sum2; xx+=4)
*longPtr++ = *longPtr2++;
}
HUnlock(theData);
}
}
line_ptr is an array of the addresses that start each line of the video
RAM. Also, the way this is written, it requires the width and the height
of the sprite to be divisible by 4. theData is just a chunk of memory
containing a stream of bytes representing the colors of the 8-bit sprites.
Can anyone think of ways to optimize this? I could post the dissassembly
but this message is long enough. (I'm still a stranger to assembly
language so I have trouble noting obvious inefficiencies in the dissasembly.)
(And if you guys don't kill me first, I'd love to post my version of
a masking copy routine so you all can tell me how horribly inefficient
THAT is.. Although it seems pretty quick.)
(How would CopyBits compare?)
Well, I guess that's about it. For the type of game I've described,
am I approaching this in the correct manner? If not, what other techniques
should I try? If so, how can I approach it more efficiently? I'm
looking for speed. I'm not sure if I've found it yet.
Again, ANY comments would be appreciated. I've only gotten this far
by generous help from Ingemar Ragnemalm, Matt Hall, Tom Dowdy, Juri
Munkki, Rick Holzgrafe, Jon Witte, Julian Harris, and others.. (Sorry
if I killed anyone's spelling; you probably don't even remember helping
me, as I first posed these types of questions back in November of '92.
I archived your messages and have referred to them often.)
Later!
- M. Scott Smith [mssmith@afterlife.ncsc.mil || umsmith@mcs.drexel.edu]
Macintosh developer, student, ski bum. Eater of Kellogg's Frosted Flakes.
"Last chance for fuel on information highway."
+++++++++++++++++++++++++++
>From john_werner@taligent.com (John Werner)
Date: Mon, 28 Feb 1994 03:18:49 GMT
Organization: Taligent, Inc.
In article <1994Feb27.234911.14595@afterlife.ncsc.mil>,
mssmith@afterlife.ncsc.mil (M. Scott Smith) wrote:
> But (at least) two things bother me: there's two copies of 512x384 bytes
> occurring for each frame of animation: first the copy of the background
> into the work buffer, then the copy of the work buffer to the screen. Not
> to mention all the copies of the sprites -- possibly up to 30.
You're right. This will be too slow, as your experiment below shows.
> Keeping a
> list of rectangles needing to be copied is another possibility, but this
> will result in a lot of overhead and required computations,
This is probably the way to do it. If you try hard enough you can optimize
the list of rectangles by merging ones that overlap or are adjacent. To
make things more complicated, you need to do this all twice: once for
copying from your background bitmap to the work buffer, then for the copy
from the work buffer to the screen. When copying from the background, you
only need to copy the areas corresponding to the sprites' old locations (to
erase them). When copying to the screen, you need the union of the old and
new sprite locations, to erase the old sprites and draw the new ones.
Another strategy would be to divide the screen up into an even grid of
rectangles. If a rectangle contains any sprites then it gets copied;
otherwise it doesn't. This would work best if you know your sprites are
usually going to be concentrated in certain areas rather than randomly
scattered around the screen.
> and numerous little copies that would probably make it slower.
You should test this before you assume it's true. If the bit depths and
color tables all match, most of the time is going to be spent writing bits
to the screen.
Other tips:
Make sure all of your bitmaps are longword-aligned.
Make sure all the color tables and bit depths match. CopyBits can slow
down a lot when they don't. With a custom blitter life will be a lot
simpler if you don't have to worry about such things.
Expand the left and right edges of areas to be copied so that they end on
byte (or word, or longword) boundaries, so CopyBits or your custom blitter
has a much simpler job to do.
> I don't think a bad prediction would be that
> with those results, I might end up with around 6 frames per second. Isn't
> that pretty bad?
Yes. You need 20 fps or so to look at all decent. 30 would be even
better.
--
John Werner john_werner@taligent.com
Taligent, Inc.
+++++++++++++++++++++++++++
>From Turly.OConnor@isltd.insignia.com (Turly OConnor)
Date: 28 Feb 1994 10:39:45 -0600
Organization: UTexas Mail-to-News Gateway
M. Scott Smith had a few questions regarding speeding up his sprite drawer.
Here's one:
- Don't bother with locking and unlocking the handle!
Since you don't call anything which moves memory, there's no point.
The trap dispatcher overhead is likely to be bigger than your entire
sprite copying loop!
- Re-organise your code so you use
do {
*longPtr++ = *spritePtr++;
} while (--xx);
instead of the for(;;) loop you've currently got.
- If you know the sprites are 32 pixels wide, unroll your x-loop so
that you write all 32 pixels at once; in fact, get rid of your x-loop
altogether.
Oops, sorry, more than one but what the heck!
Have fun!
--turly
+++++++++++++++++++++++++++
>From al@crucible.powertools.com (Al Evans)
Date: 28 Feb 94 16:51:00 GMT
Organization: PowerTools, Austin, Texas
In article <1994Feb27.234911.14595@afterlife.ncsc.mil> mssmith@afterlife.ncsc.mil (M. Scott Smith) writes:
[Sprite animation, wants to support up to 30 32X32 sprites]
> First question: will direct-screen animation work on the PowerPC, if
>the loosely-defined "correct" way of doing it is followed? From what I
>have heard and seen of the PowerPC, it doesn't seem like there's any
>inhibiting factors against using direct-screen graphics. But I haven't
>gotten my hands on a PPC compiler yet to try it out.
Consider the possibility that you may be working on the wrong thing.
First, it's difficult to beat CopyBits by much when you're using
srcCopy mode and everything is ligned up right (assuming 8-bit color
with value of ctSeed equal in offscreen GWorld and onscreen device).
Second, remember that even eliminating the offscreen-to-onscreen copy
COMPLETELY will only make you about 30% faster (which may be what you
have to do to get the performance you want). Third, remember that
CopyBits will always be supported and will work on all Macs.
[Description of animation loop: offscreen-to-offscreen copy of
entire background, offscreen-to-offscreen to sprites, offscreen-to-
onscreen of composite]
> I know there are probably ways to prevent copying the entire screen,
>and I could use some suggestions. I could keep track of a "dirty rectangle"
>that needs updating, but for my game I'll have sprites all over the screen
>so it seems like I'll need to copy the whole screen anyway. Keeping a
>list of rectangles needing to be copied is another possibility, but this
>will result in a lot of overhead and required computations, and numerous
>little copies that would probably make it slower.
My tests indicate that the overhead of maintaining a sorted list of
update Rects is small compared to the time saved in copying. Look at
it this way: if you only save 4 pixels at each side of the window,
that's 4 * 384 * 2 bytes that don't have to be moved, or enough bytes
for 3 32X32X8 sprites.
[timing tests]
>I might end up with around 6 frames per second. Isn't
>that pretty bad? For arcade games, how many "complete" screen updates / s
>are there usually? (I've also got to remind myself that I'm developing
>this on a IIfx -- which (for now) is still speedier than the average Mac.)
I've done some pretty extensive speed testing lately in finishing up
my Graphic Elements system (watch this space for announcements Real Soon
Now). I use a somewhat similar double buffering technique. I find that
I can get 8 frames/second on a Mac IIsi with 30 32X32 sprites scattered
over the screen and moving randomly. This drops to 7 fps with a "load",
i.e. collision processing. On a Quadra 800, the numbers are 33 and
29, respectively. I do not believe that these numbers can be substantially
improved without going to a different animation scheme (but I'd love
to be proved wrong:-).
[...]
> Well, I guess that's about it. For the type of game I've described,
>am I approaching this in the correct manner? If not, what other techniques
>should I try? If so, how can I approach it more efficiently? I'm
>looking for speed. I'm not sure if I've found it yet.
"Correct" is a big word, but you're approaching it in the only highly
general manner (i.e. offscreen construction, off-to-onscreen copy).
If I were you, I would look at the following possibilities: 1) Use
smaller sprites or fewer of them; 2) Keep a list of dirty Rects and
copy only what you have to; 3) Try to "offset" your frame generation
so that, for example, only 1/3 of the sprites need updating on a
given frame (of course this only works in conjunction with 2).
--Al Evans--
--
Al Evans Tu causes, tu causes
al@crucible.powertools.com C'est tout ce que tu sais faire
cs.utexas.edu!crucible!al -- LaVerdure
+++++++++++++++++++++++++++
>From mxmora@unix.sri.com (Matt Mora)
Date: 28 Feb 1994 09:33:03 -0800
Organization: SRI International, Menlo Park, CA
In article <1994Feb27.234911.14595@afterlife.ncsc.mil> mssmith@afterlife.ncsc.mil (M. Scott Smith) writes:
> I know there are probably ways to prevent copying the entire screen,
>and I could use some suggestions. I could keep track of a "dirty rectangle"
>that needs updating, but for my game I'll have sprites all over the screen
>so it seems like I'll need to copy the whole screen anyway. Keeping a
>list of rectangles needing to be copied is another possibility, but this
>will result in a lot of overhead and required computations, and numerous
>little copies that would probably make it slower.
You get lots of suggestions about optimizations but one thing you should
remember, try any move as little bytes as possible. You will never
be able to an entire screen in one tick on apples current hardware. Maybe
this will be possible in PowerPC and we will finally be able to play games
with a scrolling background. :-)
If you have many sprites union their rects and copy that data. Though
you are copying more data than you need to you should win by being able
to move longwords at a time.
Xavier
--
___________________________________________________________
Matthew Xavier Mora Matt_Mora@qm.sri.com
SRI International mxmora@unix.sri.com
333 Ravenswood Ave Menlo Park, CA. 94025
+++++++++++++++++++++++++++
>From Arsenault_C@msm.cdx.mot.com (Chris Arsenault)
Date: Mon, 28 Feb 1994 13:26:21 -0500
Organization: Motorola Codex
In article <1994Feb27.234911.14595@afterlife.ncsc.mil>,
mssmith@afterlife.ncsc.mil (M. Scott Smith) wrote:
> The type of game I'll be writing will probably be similar to Lemmings,
> in that I need to have support for lots of (fairly small) sprites. Having
> 30 separate sprites on screen and moving is not too much to ask. (It may
> be too much to program, but...) But they'll generally be 32x32 pixels or
> smaller, with room for a few larger ones. I'll write this game to fill
> the 12" monitor -- 512x384 pixels. It will only support color, probably
> require System 7, etc. And it uses "direct-screen" drawing; filling the
> video RAM with bytes for instant gratification.
> Well, I guess that's about it. For the type of game I've described,
> am I approaching this in the correct manner? If not, what other techniques
> should I try? If so, how can I approach it more efficiently? I'm
> looking for speed. I'm not sure if I've found it yet.
Some comments:
- if you have a lot of sprites moving on screen then it may be better to
optimize the background copy operation between your saved background and
your work buffer (the one you do a CopyBits to the screen with). You can
unroll a loop in assembler and refresh your work buffer real fast. Then you
can do all the real drawing in your work buffer. Given your type of game
you have to determine if the overhead of tracking and updating invalid
rects is worth the time. Generally the more smaller rects you need to
update, the easier it is to save time by just doing a real fast copy of the
buffer. I would calculate a dirty rect for all sprites drawn in the work
buffer though, so what I actually have to copy to the screen would remain
the minimal update rect. (Don't forget to adjust this update rect to the
proper multiple of 32 for both left and right edges!) Once calculated, you
use this rect to restore the background on the next pass!
- You really don't want to play with direct screen drawing for this style
of animation for a couple of reasons: Directly writing to the video memory
can get you clobbered by some graphics accellerators. If you allow the user
to switch out to the Finder and s/he changes the depth of the monitor on
the fly, and you don't check it, you're in ds trouble. Also, although you
can sync up to obtain a nice smooth animation with vertical blanking you
still can end up trying to beat the electron gun. If, in drawing directly
to video memory, you end up drawing the last item in your sprite drawlist
near the top of the screen when the vertical blanking interval is over,
you'll end up with a tearing effect. There is overhead in trying to order
sprites, both for front-back and top-bottom drawing (to provide tear-free
animation). Also, given you may have a higher refresh rate on some
monitors, you'd be playing with an unknown. (Spend more of your development
time trying to avoid hardware related issues - you'll thank me later! ;-) )
- I'm assuming that you're going to look through your GDeviceList and set
up your VBL task in the correct slot to synch with the monitor or monitors.
Again, be aware of different refresh rates for monitors.
- Sometimes you don't need a high frame rate to achieve the appearence of a
very fast frame rate. For example if you attain 30fps moving your sprites 1
pixel position on the screen you can achieve the same "look" by moving your
sprites 2 pixel positions for only 15 fps. AND... if you're tearing at
30fs, but tear-free at 15 fps...the user will prefer the smooth look vs the
choppy.
- Do everything in your offscreen buffer then use CopyBits to move the
dirtyRect to screen...even if CopyBits has to make the transition to
different bit depths, chances are it will stay ahead of the electron gun
and you'll still get robust, smooth flicker-free animation and your game
will have a nice long life. (See Inside Mac III, p20. Although the values
are off, the ideas are still valid!)
- The only time direct screen drawing is really affordable (or necessary)
is when you're doing extremely minimal updates to an existing image using
polygons and the like or performing a non-rectangular copy (for example
doing a custom block copy that skews the image to some arbitrary angle.)
(Rule of thumb - if you have a lot of game event overhead time, like
network games or computing intelligence for chars, then simplify the
graphics to absolute minimum - most successful with poly or solid color
updates) Sounds like your sprites do internal animation - if this is the
case you have to do complete draw of the new sprite each pass anyway.
Also it might be nicer to concentrate on supporting B&W versions if
possible...in terms of market there is still a lot of B&W Mac's out
there...including a lot of new PowerBooks.
BTW - in Sprite::Plot, you can increase the speed considerably by unrolling
the loop (for every iteration of the loop code overhead try to copy as many
longwords as you can!)
Good luck and put me on your beta test list!
Chris
--
#include <UsualLegalDisclaimers.h>
#define AnnoyThem "This bug's for you!"
+++++++++++++++++++++++++++
>From u9119523@sys.uea.ac.uk (Graham Cox)
Date: Tue, 1 Mar 1994 18:22:04 GMT
Organization: School of Information Systems, UEA, Norwich
In article <1994Feb27.234911.14595@afterlife.ncsc.mil>,
mssmith@afterlife.ncsc.mil (M. Scott Smith) wrote:
> Ramble alert! (This one's kinda long..)
>
> Hi gang!
>
> I found a few minutes this weekend to revisit my much-procrastinated
> tour into the development of Mac arcade games.. (Well, I haven't really
> procrastinated, I just haven't had the time. :(
>
> I've been developing a direct-screen animation toolkit which I'll
> (eventually) be using to write games. I'm now working on the "animation
> engine" -- the heart of the game where all of the animation will be
> performed.
>
[deleted]
>
> - M. Scott Smith [mssmith@afterlife.ncsc.mil || umsmith@mcs.drexel.edu]
>
> Macintosh developer, student, ski bum. Eater of Kellogg's Frosted Flakes.
>
> "Last chance for fuel on information highway."
If you're the type who likes to reinvent the wheel, (like we all are at
times!) then go ahead and don't let me stop you.
BUT- this has already been done- "SpriteWorld" (archive sites) works
identically to the way you describe, with a pair of offscreen work areas.
It generates sprites from PICT or cicn resources, and uses the time manager
to give sub-tick accuracy. It also has hooks for writing custom blitting
routines, and comes with one for 8-bit colour direct screen blitting, or
can use CopyBits. The example program turned in something like 100
frames/sec on a Centris 610 animating 5 or 6 50 x 50 pixel sprites. I got
64 frames/sec on my IIsi! It also has full layer support and collision
detection. It is stable and easy to use- I rolled it into one of my C
applications in one evening and never had the slightest trouble compiling
it.
Now I have SpriteWorld, I am never going to write another sprite-animation
routine again!
I would also say that I have nothing whatsoever to do with its author, but
I am one very satisfied "customer" -and word-of-mouth advertising is the
best kind!
A technical point- SpriteWorld uses linked lists to store the data for each
sprite, not arrays. I wonder which method is faster? I reckon that the
performance is not bound by this anyway, but on the number of pixels
blitted per frame. SpriteWorld seems to go to a lot of trouble to minimise
the number of pixels blitted per frame, adding a little code overhead to
check this, but its high performance seems to suggest that this is a good
strategy.
- ------------------------------------------------------------------------
Love & BSWK, Graham
-Everyone is entitled to their opinion, no matter how wrong they may be...
- ------------------------------------------------------------------------
+++++++++++++++++++++++++++
>From Tony Myles <tony.myles@3do.com>
Date: 1 Mar 1994 22:55:29 GMT
Organization: The 3DO Company
In article <u9119523-010394182204@case1.sys.uea.ac.uk> Graham Cox,
u9119523@sys.uea.ac.uk writes:
>If you're the type who likes to reinvent the wheel, (like we all are at
>times!) then go ahead and don't let me stop you.
>
>BUT- this has already been done- "SpriteWorld" (archive sites) works
>identically to the way you describe, with a pair of offscreen work areas.
>It generates sprites from PICT or cicn resources, and uses the time
manager
>to give sub-tick accuracy. It also has hooks for writing custom blitting
>routines, and comes with one for 8-bit colour direct screen blitting, or
>can use CopyBits. The example program turned in something like 100
>frames/sec on a Centris 610 animating 5 or 6 50 x 50 pixel sprites. I got
>64 frames/sec on my IIsi! It also has full layer support and collision
>detection. It is stable and easy to use- I rolled it into one of my C
>applications in one evening and never had the slightest trouble compiling
>it.
There will be a new version of SpriteWorld out soon. I have sped it up
about 20-30% using the custom blitter, and about 20% more on top of that
using compiled sprites. Numerous bug fixes were rolled in as well.
>Now I have SpriteWorld, I am never going to write another
sprite-animation
>routine again!
>
>I would also say that I have nothing whatsoever to do with its author,
but
>I am one very satisfied "customer" -and word-of-mouth advertising is the
>best kind!
Thanks, this is good to hear. Any chance of a SpriteWorld based version
of Desk Invaders?
>A technical point- SpriteWorld uses linked lists to store the data for
each
>sprite, not arrays. I wonder which method is faster? I reckon that the
>performance is not bound by this anyway, but on the number of pixels
>blitted per frame. SpriteWorld seems to go to a lot of trouble to
minimise
>the number of pixels blitted per frame, adding a little code overhead to
>check this, but its high performance seems to suggest that this is a good
>strategy.
Early versions of SpriteWorld used arrays, when I switched to doubly
linked lists it made no difference (for better or worse) in terms of
speed but it did greatly increase flexibility.
As far as code overhead goes, I have found that almost anything you can
do to reduce the number of pixels you have to move, results in a faster
frame rate. During the development of SpriteWorld this has proved true in
almost all cases. However, when optimizing any algorithm, you have to
keep in mind the most common case. Take for example the case of
overlapping sprites. You might go to a lot of trouble to avoid blitting
the overlapping areas of the screen more than once per frame, but if your
sprites don't overlap much (or at all) this doesn't make sense. The
overhead of calculating the difference of the overlapping rects would
just slow down the most common case. For something like SpriteWorld, this
is particularly tricky, since I don't know for sure what the most common
case will be. Indeed, there is a danger of optimizing for the most common
case too much, to where the code is no longer good for anything BUT the
most common case (which may be OK, again depending on the application).
Inevitably it becomes a question of a tradeoffs between application
specific optimizations, and code generality and reusability.
...Tony
- ---------------------------------------------
Tony Myles work: tony.myles@3do.com
The 3DO Company home: suiryu@aol.com
+++++++++++++++++++++++++++
>From deweeset@ptolemy1.rdrc.rpi.edu (Thomas E. DeWeese)
Date: 1 Mar 1994 20:52:02 GMT
Organization: Rensselaer Polytechnic Institute, Troy NY, USA
In article <1994Feb27.234911.14595@afterlife.ncsc.mil>,
M. Scott Smith <mssmith@afterlife.ncsc.mil> wrote:
>Ramble alert! (This one's kinda long..)
> I've been developing a direct-screen animation toolkit which I'll
>(eventually) be using to write games. I'm now working on the "animation
>engine" -- the heart of the game where all of the animation will be
>performed.
> The type of game I'll be writing will probably be similar to Lemmings,
>in that I need to have support for lots of (fairly small) sprites. Having
>30 separate sprites on screen and moving is not too much to ask. (It may
>be too much to program, but...) But they'll generally be 32x32 pixels or
>smaller, with room for a few larger ones. I'll write this game to fill
>the 12" monitor -- 512x384 pixels. It will only support color, probably
>require System 7, etc. And it uses "direct-screen" drawing; filling the
>video RAM with bytes for instant gratification.
Just a note, 30 32x32 sprites in a 512x384 window is pretty
crowded (in my opinion).
> But (at least) two things bother me: there's two copies of 512x384 bytes
>occurring for each frame of animation: first the copy of the background
>into the work buffer, then the copy of the work buffer to the screen. Not
>to mention all the copies of the sprites -- possibly up to 30.
Yes this is a problem. I strongly suggest the 'dirty'
rectangle solution propsed by so many others. Using an insertion sort
to order them top to bottom, left to right shouldn't be so bad, for
only 30-60 elems.
>game's I/O and logic, etc. I don't think a bad prediction would be that
>with those results, I might end up with around 6 frames per second. Isn't
>that pretty bad?
Yes, as others have noted 20-30fps is where you want to be.
As for your code:
Keep your pixmap locked down, actually it doesn't matter too
much for this function since you can't cause a handle to move.
Don't mess up a nice tight function with stuff like:
if (data_allocated == 1)
Test it once before you start blitting.
This should give you a pretty good starting place to start
optomizing your asm. The following is off the top of my head so it
might not compile.
long rowBytesDiv4; /* row bytes divided by 4 (or >> 2 if your smart) */
void
Sprite::Plot(register long x, register long y)
{
register long *longPtr, *longPtr2;
register long *endLn, *endImg;
register long rowOffset = rowBytesDiv4 - width; /* possibly precomputed */
longPtr2 = (long *)(*theData);
endImg = longPtr2+width*height;
longPtr = (long *)(x + theScreen->line_ptr[y]);
while (longPtr2<endImg)
{
longPtr += rowOffset;
endLn = longPtr+width;
while (longPtr<endLn)
*longPtr++ = *longPtr2++; /* if width is known unroll this using
* 68000 post increment stuff, and movem
*/
}
}
> (How would CopyBits compare?)
CopyBits has a fair amount of over head so for small blits it
loses (it needs to check colorTables, bit depths, clipRgns, and all
that junk) But once it get's going you won't be able to beat it. So
for large general area copies you can only hope to match it's speed.
But for small known size areas you can cream it.
BTW the above code won't get you any closer to animating
512x384 at 30fps (if it did, we'd have Sonic THH on the market by
now), it will make it possible to animate your 32x32 icons at a reasonable
speed if you use a dirty rectangle scheme. Also don't forget your basic
math. If your sprite moves < 13 pixes blit one rectangle that encloses both
the new, and old location (45x45 = 2025 pixles, 32x32x2 = 2048 pixels).
+-----+ +--------+
|##+-----+ |##### | one larger blit
|##|.....| two 32x32 blits |##......|
+--|.....| | ......|
+-----+ +--------+
There is a trade off in that fixed size blits will be faster,
due to loop unrolling etc... than a variable sized loop (so you might
try haveing fixed width, and variable height, so the width is unrolled
and the height isn't. You might have a function for widths of 32, 36,
40, and 44. You could then have an array of function pointers for
dispatching appropriately.
--
Thomas DeWeese "If it helps you, just think of people using swear
deweeset@rdrc.rpi.edu words as truck drivers on the Information Superhighway"
-- Matthias Neeracher
+++++++++++++++++++++++++++
>From d88-jwa@mumrik.nada.kth.se (Jon Wdtte)
Date: 2 Mar 1994 10:40:16 GMT
Organization: Royal Institute of Technology, Stockholm, Sweden
In <2l09tj$4i9@usenet.rpi.edu> deweeset@ptolemy1.rdrc.rpi.edu (Thomas E. DeWeese) writes:
>long rowBytesDiv4; /* row bytes divided by 4 (or >> 2 if your smart) */
>>2 isn't very smart. It has strange semantics (precedence, signed/unsigned
etc) as well as is harder to read than a simple /4.
If your compiler doesn't generate a fast shift instead of a slow compile,
you have MUCH worse optimizations to worry about than hand-coding the
shift.
--
-- Jon W{tte, h+@nada.kth.se, Mac Hacker Deluxe --
"It was, in fact, cool as all get-out. Fortunately it was a little
too late (historically speaking) to be groovy."
-- Dennis Pelton
+++++++++++++++++++++++++++
>From andrewwelc@aol.com (AndrewWelc)
Date: 2 Mar 1994 05:23:04 -0500
Organization: America Online, Inc.
>>
BUT- this has already been done- "SpriteWorld" (archive sites) works
identically to the way you describe, with a pair of offscreen work areas.
<<
Sure -- SpriteWorld is good architecture (if you aren't going to do anything
with scrolling backgrounds, etc.), but in terms of raw animation speed, forget
it.
The custom drawing routine just aren't all that optimized -- I recommend
writing your own if you plan to animate a reasonable number of sprites on
lower-end machines. For the PowerPC, just use CopyBits().
Andrew
+++++++++++++++++++++++++++
>From andrewwelc@aol.com (AndrewWelc)
Date: 2 Mar 1994 05:23:07 -0500
Organization: America Online, Inc.
>>
BUT- this has already been done- "SpriteWorld" (archive sites) works
identically to the way you describe, with a pair of offscreen work areas.
<<
Sure -- SpriteWorld is good architecture (if you aren't going to do anything
with scrolling backgrounds, etc.), but in terms of raw animation speed, forget
it.
The custom drawing routine just aren't all that optimized -- I recommend
writing your own if you plan to animate a reasonable number of sprites on
lower-end machines. For the PowerPC, just use CopyBits().
Andrew
+++++++++++++++++++++++++++
>From andrewwelc@aol.com (AndrewWelc)
Date: 2 Mar 1994 05:23:08 -0500
Organization: America Online, Inc.
>>
BUT- this has already been done- "SpriteWorld" (archive sites) works
identically to the way you describe, with a pair of offscreen work areas.
<<
Sure -- SpriteWorld is good architecture (if you aren't going to do anything
with scrolling backgrounds, etc.), but in terms of raw animation speed, forget
it.
The custom drawing routine just aren't all that optimized -- I recommend
writing your own if you plan to animate a reasonable number of sprites on
lower-end machines. For the PowerPC, just use CopyBits().
Andrew
+++++++++++++++++++++++++++
>From andrewwelc@aol.com (AndrewWelc)
Date: 2 Mar 1994 05:23:05 -0500
Organization: America Online, Inc.
>>
BUT- this has already been done- "SpriteWorld" (archive sites) works
identically to the way you describe, with a pair of offscreen work areas.
<<
Sure -- SpriteWorld is good architecture (if you aren't going to do anything
with scrolling backgrounds, etc.), but in terms of raw animation speed, forget
it.
The custom drawing routine just aren't all that optimized -- I recommend
writing your own if you plan to animate a reasonable number of sprites on
lower-end machines. For the PowerPC, just use CopyBits().
Andrew
+++++++++++++++++++++++++++
>From andrewwelc@aol.com (AndrewWelc)
Date: 2 Mar 1994 05:23:16 -0500
Organization: America Online, Inc.
>>
BUT- this has already been done- "SpriteWorld" (archive sites) works
identically to the way you describe, with a pair of offscreen work areas.
<<
Sure -- SpriteWorld is good architecture (if you aren't going to do anything
with scrolling backgrounds, etc.), but in terms of raw animation speed, forget
it.
The custom drawing routine just aren't all that optimized -- I recommend
writing your own if you plan to animate a reasonable number of sprites on
lower-end machines. For the PowerPC, just use CopyBits().
Andrew
+++++++++++++++++++++++++++
>From andrewwelc@aol.com (AndrewWelc)
Date: 2 Mar 1994 05:23:18 -0500
Organization: America Online, Inc.
>>
BUT- this has already been done- "SpriteWorld" (archive sites) works
identically to the way you describe, with a pair of offscreen work areas.
<<
Sure -- SpriteWorld is good architecture (if you aren't going to do anything
with scrolling backgrounds, etc.), but in terms of raw animation speed, forget
it.
The custom drawing routine just aren't all that optimized -- I recommend
writing your own if you plan to animate a reasonable number of sprites on
lower-end machines. For the PowerPC, just use CopyBits().
Andrew
+++++++++++++++++++++++++++
>From andrewwelc@aol.com (AndrewWelc)
Date: 2 Mar 1994 05:23:12 -0500
Organization: America Online, Inc.
>>
BUT- this has already been done- "SpriteWorld" (archive sites) works
identically to the way you describe, with a pair of offscreen work areas.
<<
Sure -- SpriteWorld is good architecture (if you aren't going to do anything
with scrolling backgrounds, etc.), but in terms of raw animation speed, forget
it.
The custom drawing routine just aren't all that optimized -- I recommend
writing your own if you plan to animate a reasonable number of sprites on
lower-end machines. For the PowerPC, just use CopyBits().
Andrew
+++++++++++++++++++++++++++
>From andrewwelc@aol.com (AndrewWelc)
Date: 2 Mar 1994 05:23:13 -0500
Organization: America Online, Inc.
>>
BUT- this has already been done- "SpriteWorld" (archive sites) works
identically to the way you describe, with a pair of offscreen work areas.
<<
Sure -- SpriteWorld is good architecture (if you aren't going to do anything
with scrolling backgrounds, etc.), but in terms of raw animation speed, forget
it.
The custom drawing routine just aren't all that optimized -- I recommend
writing your own if you plan to animate a reasonable number of sprites on
lower-end machines. For the PowerPC, just use CopyBits().
Andrew
+++++++++++++++++++++++++++
>From andrewwelc@aol.com (AndrewWelc)
Date: 2 Mar 1994 05:23:15 -0500
Organization: America Online, Inc.
>>
BUT- this has already been done- "SpriteWorld" (archive sites) works
identically to the way you describe, with a pair of offscreen work areas.
<<
Sure -- SpriteWorld is good architecture (if you aren't going to do anything
with scrolling backgrounds, etc.), but in terms of raw animation speed, forget
it.
The custom drawing routine just aren't all that optimized -- I recommend
writing your own if you plan to animate a reasonable number of sprites on
lower-end machines. For the PowerPC, just use CopyBits().
Andrew
+++++++++++++++++++++++++++
>From Tony Myles <tony.myles@3do.com>
Date: 2 Mar 1994 18:15:58 GMT
Organization: The 3DO Company
In article <2l1pe8$ehi@rmg01.prod.aol.net> AndrewWelc, andrewwelc@aol.com
writes:
>Sure -- SpriteWorld is good architecture (if you aren't going to do
anything
>with scrolling backgrounds, etc.), but in terms of raw animation speed,
forget
>it.
Forget it? Oooh, that stings. ;-)
>The custom drawing routine just aren't all that optimized -- I recommend
>writing your own if you plan to animate a reasonable number of sprites on
>lower-end machines.
So do I. I have improved the blitters in SpriteWorld about 20%, but they
were really never intended to be used as is. They more or less serve as
examples, so that you can write your own that are more specific to your
animation. (ie. assuming 32x32 sprites or whatever).
>For the PowerPC, just use CopyBits().
Decide to give up on your PowerPC sprite compiler, Andrew?
...Tony
- ---------------------------------------------
Tony Myles work: tony.myles@3do.com
The 3DO Company home: suiryu@aol.com
+++++++++++++++++++++++++++
>From al@crucible.powertools.com (Al Evans)
Date: 2 Mar 94 19:15:31 GMT
Organization: PowerTools, Austin, Texas
In another article in this thread (which has unfortunately expired from
my news spool), John Werner (john_werner@taligent.com) suggested a
strategy of dividing up the background into a grid of rectangles to limit
the amount of drawing that would be required for each update.
Since this kind of thing is easy to implement in Graphic Elements (took
me 26 lines of code, boast boast), I ran some tests. In these tests,
a) the moving graphics were 42 X 42 pixels, and b) the background
which was updated in any particular cell was the union of the rects
of all changed graphics in that cell. I used two different sets of
test conditions.
In the first test, the graphics were all in two even lines, moving to the
right to the edge of the window, then dropping down half their height
and moving to the left. When they hit the bottom of the window, they
moved back to the top left corner.
Using 16 of these graphics on a Quadra 800, I found that the frame
rate varied from 60 to 71 fps when the background was a single
cell. This is explained by the fact that when a graphic on the
bottom right "dropped off" to the top left, almost the entire
background (512 X 384) was included in the update.
A few quick tests indicated that the optimum dimensions for the
background grid were about 3X the "sprite" size. Dividing the
background into 128X128 cells gave me frame rates of 63 to 68
fps -- not as high on the high end because of the increased
overhead of processing 12 background elements instead of 1,
but better on the low end. The improvement in the "look" of the
movement was better than the figures would indicate, since these
are average frame rates over 30 seconds.
This technique really shone, though, when the graphics were in
random motion over the background. For the same 16 graphics, I
got an average of 46 fps using the 128X128 cells, as compared
to 39 fps using a single background cell. And the difference
increased as the number of graphics dropped: 80 fps as compared
to 60 with 8 graphics, 175 as compared to 96 with 4. Once
again, the "look" was greatly improved.
I'm sure that's more than you ever wanted to know. But I've found
that it's very difficult to predict the effect of an "improvement"
in a high-performance animation system, and thought I'd share these
numbers since I'm in a position to do so.
--Al Evans--
--
Al Evans Tu causes, tu causes
al@crucible.powertools.com C'est tout ce que tu sais faire
cs.utexas.edu!crucible!al -- LaVerdure
+++++++++++++++++++++++++++
>From mxmora@unix.sri.com (Matt Mora)
Date: 2 Mar 1994 13:28:29 -0800
Organization: SRI International, Menlo Park, CA
In article <421@crucible.powertools.com> al@crucible.powertools.com (Al Evans) writes:
>I'm sure that's more than you ever wanted to know. But I've found
>that it's very difficult to predict the effect of an "improvement"
>in a high-performance animation system, and thought I'd share these
>numbers since I'm in a position to do so.
Can you post the code? It would be cool to try it on other macs to see
how things differ.
Xavier
--
___________________________________________________________
Matthew Xavier Mora Matt_Mora@qm.sri.com
SRI International mxmora@unix.sri.com
333 Ravenswood Ave Menlo Park, CA. 94025
+++++++++++++++++++++++++++
>From ua025@freenet.Victoria.BC.CA (Cody Jones)
Date: Fri, 4 Mar 1994 10:37:46 GMT
Organization: The Victoria Freenet Association (VIFA), Victoria, B.C., Canada
I'll just put in my 2 bits... I'm also doing a game w/ direct-screen
writing, a fair number of 32x32 sprites, etc... I ONLY use direct writing
because I've had it with letting the system do it for me. Besides, my
game will have a MOD playing so my code needs all the speed it can get.
Anyway, a suggestion: Try and make use of the 68040's MOVE16 command.
You might keep an array of flags, one for each row on the screen. If the
row is set, update it - the entire row, that is. The MOVE16 will probably
be fast enough to compensate for copying what you don't need to on each
line: on my Tempest (aka. 660AV) I was able to move over 80 megs/second
with it! For a 512x384 screen, you can sure get a decent frame rate with
that - well, well over 60 fps.
I haven't actually implemented this 'row updating' idea, only a routine to
test the MOVE16's speed. Of course this method won't work on 68030's...
your program would have to check & call the proper update-routine
according to the processor.
Cody Jones of Zerius Development
ua025@freenet.victoria.bc.ca
--
+++++++++++++++++++++++++++
>From andrewwelc@aol.com (AndrewWelc)
Date: 4 Mar 1994 10:32:04 -0500
Organization: America Online, Inc.
>>
I haven't actually implemented this 'row updating' idea, only a routine to
test the MOVE16's speed. Of course this method won't work on 68030's...
your program would have to check & call the proper update-routine
according to the processor.
<<
I'm curious what other nitty gritty write-directly-to-the-screen-in-assmebler
game programmers out there (like me) are doing for the PowerPC....?
Andrew Welch
Ambrosia Software
+++++++++++++++++++++++++++
>From Ron_Hunsinger@bmug.org
Date: Tue, 01 Mar 1994 15:37:18 PST
Organization: BMUG, Inc.
M. Scott Smith,mssmith@afterlife.ncsc.mil writes:
> But (at least) two things bother me: there's two copies of 512x384 bytes
>occurring for each frame of animation: first the copy of the background
>into the work buffer, then the copy of the work buffer to the screen. Not
>to mention all the copies of the sprites -- possibly up to 30.
That worries me too. (I developed a sprite engine on the Plus, and ran
into the same kinds of problems you're running into.)
> No optimizations:356 frames / 30 seconds or 11.87 frames/s
> Compiled for 68020 and up,
> with all Symantec C++ opts: 554 frames / 30 seconds or 18.47 frames/s
And this is the main problem, in a nutshell. Even on a B/W 512x342 screen,
there just isn't time to be copying screen-sized data around. The Plus
simply didn't have that kind of horsepower, and if you are running on
a faster machine you are probably using color and/or a bigger screen, and
the problem is still there. Probably will always be there, because I
see no reason for the screenSize:processorPower ratio to change much.
> I know there are probably ways to prevent copying the entire screen,
>and I could use some suggestions. I could keep track of a "dirty rectangle"
>that needs updating, but for my game I'll have sprites all over the screen
>so it seems like I'll need to copy the whole screen anyway. Keeping a
>list of rectangles needing to be copied is another possibility, but this
>will result in a lot of overhead and required computations, and numerous
>little copies that would probably make it slower.
I used the "dirty rectangle" approach, but NOT by keeping a separate
rectangle for each sprite. Remember, you're trying to minimize copying,
so you don't want to copy the data twice if two sprites overlap.
Instead, I divided the screen into a bunch of rectangular zones, each
rectangular and nicely aligned. In my case, I made the zones 16x16
pixels, so that the entire screen was like 32x20 zones. (For an
effective screen size of 512x320 pixels, meaning I discarded 22 pixels
in the vertical dimension.) Then I kept track of which zones were
dirty, using a table of 20 longwords. You might call this the "dirty
zone" method.
Taking the union of draw lists becomes a snap. (You have to update not
only the zones where the sprites are now, but also the zones where they
were last time.) Just keep two dirty zone lists: one for the work area,
to keep track of which zones differ from the background; and one for the
screen, for all the zones that need to be updated from the work area.
When I actually copied the data to the screen, I walked the dirty zone
table, and copied each dirty zone directly to the screen using 16
consecutive MOVE.W instructions. Remember, I was doing this on a Plus,
which had a 16-bit data bus and no cache. (At the time, color and the
Mac II were only rumors.)
I was able to get 30 frames per second on a Plus, with a few hundred
sprites moving on the screen at once. Looked nice. Since the zones get
updated in top-to-bottom order, I got no flicker even though I made no
effort to synchronize with vertical retrace.
If I were to do it again, I would use larger zones, keeping them
longword aligned but large enough so that the width of the screen would
still not exceed 32 zones. And although writing directly to the screen
is faster, I think now I would seriously consider using CopyBits for the
final copy. I did not appreciate at the time how fragile direct screen
manipulation makes your program. I would probably try to combine
horizontally adjacent zones into a single CopyBits call, to minimize
CopyBit's setup overhead.
-Ron Hunsinger
+++++++++++++++++++++++++++
>From mssmith@afterlife.ncsc.mil (M. Scott Smith)
Date: Sun, 6 Mar 1994 01:30:05 GMT
Organization: The Great Beyond
Hi gang!
I want to extend a very loud "thank you!" to everyone for their messages
concerning speeding up my animation.
A week or so ago, I brainstormed out loud about a method for doing smooth
animation in a game that might potentially have a lot of small sprites. The
easiest method I could think of was to keep two offscreen buffers, one a
"background" buffer (always containing the pure background) and another a
"work" buffer, where I would copy the background and then stick sprites on.
Finally, I would copy from the work buffer to the screen.
But my suggested method (while certainly easiest) of copying the entire
buffer first from background to work area, and then work area to screen,
was, by my own testing, slow on a IIfx in 8-bit. I asked for any
suggestions, including whether or not "dirty rectangle" approaches would
be faster. I also posted some code and asked for suggestions on
optimization.
Well, dozens of people responded on the net and in e-mail, and every
single comment I received was of great help.
First, people made code-level suggestions for squeezing more speed out
of my algorithm, and I learned some new optimizing techniques that I'll
be using from now on.
The general concensus seems to be that the best approach to updating the
screen as quick as possible is to use "dirty rectangles" or "dirty zones."
In some way, maintain areas which you can flag as "dirty" (meaning they
have had activity that requires updating). While I pondered over whether or
not this might be slow -- after all, maintaing such a list can require quite
a few operations -- people said that it will almost always be less expensive
than copying all of the data in an entire screen. And that makes sense to
me now. Efficient methods of maintaining such lists were presented.
I was reminded that libraries such as SpriteWorld exist and already do
much of what I want, but I don't mind "reinventing the wheel" because this
is a learning experience for me. (This is the same reason I don't use
MacApp or TCL but instead write my own class libraries; I may not do it
as well, but I learn how it's done. Maybe that's stubborn, but as a kid
I took everything apart to see how it works; I don't like "black boxes."
Once I learn how to develop my own class libraries, I'll be happy to use
other ones since I'll have an idea of how they were written.)
I really like the kind of discussion that has been going on in this
thread; it's thought-provoking. It'd be great if it could continue;
there's lots of general issues involved in game writing which are a little
abstract.
- -[fade out, fade in..]---
One of the other things that has been eating at me is the best way to
handle "timing." The best method will be to make the animation machine-
independent. If a sprite is moving across the screen at a certain speed
on the PowerMac's, it should move at the same speed on an LC. This may
mean skipping frames in the animation -- or moving the sprite along 4
pixels at a time instead of 2.
I've mulled over this one a bit, but haven't come up with anything
that I'm particularly thrilled about. Any suggestions?
And on another note entirely, say you have some type of "animated
background." Such as a flaming torch on the wall of a castle. The
flame flickers and throws out dancing light along the wall. But it's
always in the background -- it's animated just like sprites, but it
doesn't interact with the (foreground) sprites.
Something I briefly tried some time ago was putting the code for
these types of animations in background tasks. Is this more trouble
than it's worth? (Is it better to handle all of the animation in the
same place?)
Thanks again for all the help..
Scott
- -
M. Scott Smith (mssmith@afterlife.ncsc.mil || umsmith@mcs.drexel.edu)
Macintosh developer. Student. Ski bum. Eater of Ben and Jerry's ice cream.
+++++++++++++++++++++++++++
>From ua025@freenet.Victoria.BC.CA (Cody Jones)
Date: Sun, 6 Mar 1994 02:26:26 GMT
Organization: The Victoria Freenet Association (VIFA), Victoria, B.C., Canada
" One of the other things that has been eating at me is the best way to
handle "timing." The best method will be to make the animation machine-
independent. If a sprite is moving across the screen at a certain speed
on the PowerMac's, it should move at the same speed on an LC. This may
mean skipping frames in the animation -- or moving the sprite along 4
pixels at a time instead of 2."
One way I use is this: Keep track of the last time your update routine
was called. When you get to the update again, see how many ticks have
passed, and for each one, call your update routine. Thus your rout always
gets called 60 times a second... well, kind of.
After that you output the frame. This method has the advantage you are
looking for. No matter how bad the fps rate, objects always move at the
same rate.
Cody Jones, Zerius Development
ua025@freenet.victoria.bc.ca
voltaire@amtsgi.bc.ca
--
+++++++++++++++++++++++++++
>From alex@metcalf.demon.co.uk (Alex Metcalf)
Date: Sun, 6 Mar 1994 11:48:05 GMT
Organization: Demon Internet
>
> One of the other things that has been eating at me is the best way to
> handle "timing." The best method will be to make the animation machine-
> independent. If a sprite is moving across the screen at a certain speed
> on the PowerMac's, it should move at the same speed on an LC. This may
> mean skipping frames in the animation -- or moving the sprite along 4
> pixels at a time instead of 2.
>
> I've mulled over this one a bit, but haven't come up with anything
> that I'm particularly thrilled about. Any suggestions?
>
> And on another note entirely, say you have some type of "animated
> background." Such as a flaming torch on the wall of a castle. The
> flame flickers and throws out dancing light along the wall. But it's
> always in the background -- it's animated just like sprites, but it
> doesn't interact with the (foreground) sprites.
>
> Something I briefly tried some time ago was putting the code for
> these types of animations in background tasks. Is this more trouble
> than it's worth? (Is it better to handle all of the animation in the
> same place?)
>
> Thanks again for all the help..
>
> Scott
In my game, I have a simple loop of game code, and I use quite simple
code to determine a standard game speed for all Macs:
{
long tTicks;
tTicks = TickCount ();
GameLoop ();
while (TickCount () - tTicks < kLoopSpeed);
}
where kLoopSpeed, on my game, is 2. I know this method isn't all that
accurate, but it's good enough for what I'm doing.
As for the flickering torches idea... that shouldn't be a problem.
Just make the torch a sprite just like the others, but make sure that it's
one of the first ones copied across to your work area, before any of your
moving sprites are copied. That way, anything that passes "over it" will be
copied on top of it, and it will look like the torch is behind your main
(moving) sprites.
Hope this helps,
Alex
--
Alex Metcalf, Mac programmer in C, C++, HyperTalk, assembler
Internet, AOL, BIX: alex@metcalf.demon.co.uk
AppleLink: alex@metcalf.demon.co.uk@internet#
CompuServe: INTERNET:alex@metcalf.demon.co.uk
Delphi: alex@metcalf.demon.co.uk@inet#
FirstClass: alex@metcalf.demon.co.uk,Internet
Fax (UK): (0570) 45636
Fax (US / Canada): 011 44 570 45636
+++++++++++++++++++++++++++
>From fixer@faxcsl.dcrt.nih.gov (Chris Gonna' Find Ray Charles Tate)
Date: Sun, 6 Mar 1994 20:54:35 GMT
Organization: DCRT, NIH, Bethesda, MD
In article <alex-060394114457@metcalf.demon.co.uk>, alex@metcalf.demon.co.uk (Alex Metcalf) writes:
>Someone named Scott writes: (sorry; I lost the attribution!)
>>
>> One of the other things that has been eating at me is the best way to
>> handle "timing." The best method will be to make the animation machine-
>> independent. If a sprite is moving across the screen at a certain speed
>> on the PowerMac's, it should move at the same speed on an LC. This may
>> mean skipping frames in the animation -- or moving the sprite along 4
>> pixels at a time instead of 2.
>>
>> I've mulled over this one a bit, but haven't come up with anything
>> that I'm particularly thrilled about. Any suggestions?
> In my game, I have a simple loop of game code, and I use quite simple
>code to determine a standard game speed for all Macs:
>
>{
> long tTicks;
>
> tTicks = TickCount ();
> GameLoop ();
> while (TickCount () - tTicks < kLoopSpeed);
>}
>
>where kLoopSpeed, on my game, is 2. I know this method isn't all that
>accurate, but it's good enough for what I'm doing.
Ack! Phtui!
(Sorry; I got a little carried away. :-)
This might be reasonable if your animation speed is high, but it *does*
have the unfortunate property that it locks up the rest of the machine
while waiting for an animation interval to pass.
Why not set up a simple Time Manager routine to set a flag somewhere
that means 'it's time to draw another animation step?' This is
particularly nice in that you can have more than one Time Manager
routine that set different flags for different movement rates. That
way, you don't need the movement rates to necessarily be integer
multiples of some base rate (other than the rate of traversal of the
main loop, of course).
Also, I *believe* that a Time Manager task doesn't take up any
execution time while it's pending - is this right? I was of the impression
that a pending Time Manager task is just an entry in the task queue,
until such time as the Time Manager decides it's time to call it. If
this is the case, then you avoid any 'check to see if it's time yet'
overhead.
Furthermore (:-), this automatically gives you 'simulated' fixed-point
movement speeds - i.e. not integer numbers of pixels per step in any
given direction. Not having integer pixels/step speeds goes a looooong
way towards making your animation look smooth, especially at lower object
movement speeds.
(Good luck, by the way! And remember that the Time Manager is your friend!)
- --------------------------------------------------------------------------
Christopher Tate | "I hate writing, and I hate statistics, but
MSD, Inc. | most of all I hate writing about statistics.
| I'd rather go to the dentist; at least there
fixer@faxcsl.dcrt.nih.gov | you get to spit." -- Ed Sewell
+++++++++++++++++++++++++++
>From alex@metcalf.demon.co.uk (Alex Metcalf)
Date: Sun, 6 Mar 1994 23:15:50 GMT
Organization: Demon Internet
In article <1994Mar6.205435.229@alw.nih.gov>, fixer@faxcsl.dcrt.nih.gov
(Chris Gonna' Find Ray Charles Tate) wrote:
> In article <alex-060394114457@metcalf.demon.co.uk>, alex@metcalf.demon.co.uk (Alex Metcalf) writes:
> >Someone named Scott writes: (sorry; I lost the attribution!)
> >>
> >> One of the other things that has been eating at me is the best way to
> >> handle "timing." The best method will be to make the animation machine-
> >> independent. If a sprite is moving across the screen at a certain speed
> >> on the PowerMac's, it should move at the same speed on an LC. This may
> >> mean skipping frames in the animation -- or moving the sprite along 4
> >> pixels at a time instead of 2.
> >>
> >> I've mulled over this one a bit, but haven't come up with anything
> >> that I'm particularly thrilled about. Any suggestions?
>
> > In my game, I have a simple loop of game code, and I use quite simple
> >code to determine a standard game speed for all Macs:
> >
> >{
> > long tTicks;
> >
> > tTicks = TickCount ();
> > GameLoop ();
> > while (TickCount () - tTicks < kLoopSpeed);
> >}
> >
> >where kLoopSpeed, on my game, is 2. I know this method isn't all that
> >accurate, but it's good enough for what I'm doing.
>
> Ack! Phtui!
>
> (Sorry; I got a little carried away. :-)
>
> This might be reasonable if your animation speed is high, but it *does*
> have the unfortunate property that it locks up the rest of the machine
> while waiting for an animation interval to pass.
>
> Why not set up a simple Time Manager routine to set a flag somewhere
> that means 'it's time to draw another animation step?' This is
> particularly nice in that you can have more than one Time Manager
> routine that set different flags for different movement rates. That
> way, you don't need the movement rates to necessarily be integer
> multiples of some base rate (other than the rate of traversal of the
> main loop, of course).
Ack! Phtui!
That's all fine and well, but if your game doesn't have an event loop
(as most arcade games don't, since it takes too much CPU time for
background processing), there's nothing else to do while you're waiting for
the next animation interval!
But it's a good idea. :-)
Alex
+++++++++++++++++++++++++++
>From s_heidri@iraul1.ira.uka.de (Dietmar Heidrich)
Date: 7 Mar 1994 13:58:31 GMT
Organization: University of Karlsruhe, FRG
In article <Arsenault_C-280294132621@134.33.101.226>, Arsenault_C@msm.cdx.mot.com (Chris Arsenault) writes:
|> Some comments:
[...]
|> - Do everything in your offscreen buffer then use CopyBits to move the
|> dirtyRect to screen...even if CopyBits has to make the transition to
|> different bit depths, chances are it will stay ahead of the electron gun
|> and you'll still get robust, smooth flicker-free animation and your game
|> will have a nice long life. (See Inside Mac III, p20. Although the values
|> are off, the ideas are still valid!)
I am no Mac programmer, but on other platforms you can switch video buffers
for games instead of copying everything you already have drawn. Is there
no way to do that OS compliant on the Mac ? I think CopyBits() will be too
slow for action games if you need to copy 640x480x8bit = 307200 bytes per
frame. For 30 frames/s update rate, this yields 9 MB/s transfer rate eaten
up only for CopyBits(). Assuming you can transfer 16 bytes via burst (giving
576000 bursts needed) in 20 clock cycles, this means 46% CPU time on a 25 MHz
68040.
--
Dietmar Heidrich, Universitaet Karlsruhe, Germany
"Die Hoffnung auf den Tod ist das einzige, was mich am Leben erhaelt."
+++++++++++++++++++++++++++
>From rmah@panix.com (Robert S. Mah)
Date: Tue, 08 Mar 1994 01:29:01 -0500
Organization: One Step Beyond
s_heidri@iraul1.ira.uka.de (Dietmar Heidrich) wrote:
> I am no Mac programmer, but on other platforms you can switch video buffers
> for games instead of copying everything you already have drawn. Is there
> no way to do that OS compliant on the Mac ?
Nope.
> I think CopyBits() will be too slow for action games if you need to copy
> 640x480x8bit = 307200 bytes per frame. For 30 frames/s update rate, this
> [...]
Tell that to those who use CopyBits to write arcade games :-). Seriouslly,
it's possible, it's just not easy.
Cheers,
Rob
________________________________________________________________________
Robert S. Mah One Step Beyond rmah@panix.com
+++++++++++++++++++++++++++
>From sigurasg@rhi.hi.is (Sigurdur Asgeirsson)
Date: 8 Mar 1994 11:25:16 GMT
Organization: University of Iceland
In <2lfbu7INN597@iraun1.ira.uka.de> s_heidri@iraul1.ira.uka.de (Dietmar Heidrich) writes:
>In article <Arsenault_C-280294132621@134.33.101.226>, Arsenault_C@msm.cdx.mot.com (Chris Arsenault) writes:
[snip]
>I am no Mac programmer, but on other platforms you can switch video buffers
>for games instead of copying everything you already have drawn. Is there
>no way to do that OS compliant on the Mac ?
[snip]
There is a well defined way to do this for color-quickdraw capable
video devices. The video driver interface includes calls to check how
many video pages are available, find their baseaddresses and to switch
between video pages. It seems that this feature is little enough used
though that newer video cards don't bother to support multiple video
pages, even if they have the video RAM needed, the Quadras for instance
don't seem to support multiple video pages.
--
Sigurdur Asgeirsson | "Well you know, C isn't that hard, void (*(*f[])())()
Kambasel 26 | for instance declares f as an array of unspecified
109 Reykjavik, Iceland | size, of pointers to functions that return pointers to
sigurasg@rhi.hi.is | functions that return void... I think"
+++++++++++++++++++++++++++
>From mgleason@cse.unl.edu (Mike Gleason)
Date: 9 Mar 1994 02:09:38 GMT
Organization: NCEMRSoft
|s_heidri@iraul1.ira.uka.de (Dietmar Heidrich) wrote:
|> I am no Mac programmer, but on other platforms you can switch video buffers
|> for games instead of copying everything you already have drawn. Is there
|> no way to do that OS compliant on the Mac ?
|Nope.
That's pretty depressing. The Sega Genesis and Commodore Amiga, which
use the same damn 68000 in the Mac Plus I use, get phemomenal performance.
Ever play Sonic the Hedgehog? That should be able to be done on a mac.
Hard to believe... I think the Amiga uses a Screen pointer, which is
changeable by the programmer, so that to do very fast screen scrolling,
all you need to do is set the screen pointer to something else. It makes
no sense to me that you have to re-copy the whole damn screen if all you
want to do is scroll the screen downward a pixel.
--
______________________________________________________________________________
mike gleason mgleason@cse.unl.edu NCEMRSoft, baby!
+++++++++++++++++++++++++++
>From Arsenault_C@msm.cdx.mot.com (Chris Arsenault)
Date: Tue, 08 Mar 1994 12:35:30 -0500
Organization: Motorola Codex
In article <alex-060394231343@metcalf.demon.co.uk>,
alex@metcalf.demon.co.uk (Alex Metcalf) wrote:
> That's all fine and well, but if your game doesn't have an event loop
> (as most arcade games don't, since it takes too much CPU time for
> background processing), there's nothing else to do while you're waiting for
> the next animation interval!
One of the things I do is to switch in and out of a main event loop. When
running time critical game code I stay out of the main event loop, working
only with specific keypresses etc. When I see a special key (such as the
space bar) I switch in and out of the main event loop where I handle events
normally. The nice part about this approach is I have very clean/fast
animation without background process relinquish jitters, but I can still
handle menus, application switching and the like.
BTW, when you're the foreground process you can tell the system that you
really want all the time you can by setting the WaitNextEvent sleep
parameter to 0.
Chris
--
#include <UsualLegalDisclaimers.h>
+++++++++++++++++++++++++++
>From Arsenault_C@msm.cdx.mot.com (Chris Arsenault)
Date: Tue, 08 Mar 1994 12:51:42 -0500
Organization: Motorola Codex
In article <2lfbu7INN597@iraun1.ira.uka.de>, s_heidri@iraul1.ira.uka.de
(Dietmar Heidrich) wrote:
> I am no Mac programmer, but on other platforms you can switch video buffers
> for games instead of copying everything you already have drawn. Is there
> no way to do that OS compliant on the Mac ? I think CopyBits() will be too
> slow for action games if you need to copy 640x480x8bit = 307200 bytes per
> frame. For 30 frames/s update rate, this yields 9 MB/s transfer rate eaten
> up only for CopyBits(). Assuming you can transfer 16 bytes via burst (giving
> 576000 bursts needed) in 20 clock cycles, this means 46% CPU time on a 25 MHz
> 68040.
No. Not when focusing on market share.
You're right about video page flipping being CPU intensive. That's why you
don't see a lot of Mac video games that do full frame (640x480) flipping
and if you do the frames are usually small (ever seen QuickTime movies
playing at full speed?).
Actually, there is a tradeoff involved. By using CopyBits we gain
simplicity in handling numerous video configurations and application
longevity. What we lose is speed. We don't have a mode 13h or X. If we
draw using Toolbox trap calls to memory on a video card, then we have to
run over NuBus. (number of draw calls * (Trap dispatch overhead + NuBus
overhead + actual operation) = too expensive).
BTW - there are video cards out there that support several frame buffers
(GWorlds). But they are more likely to be found in high end publishing
systems than in the target game Mac - the LCIII.
IMHO, I would love to see hardware supported video DMA. I've worked with
the Amiga and it was great to have the blitter and copper.
Chris
--
#include <UsualLegalDisclaimers.h>
+++++++++++++++++++++++++++
>From flavius@bga.com (Flavius Goombius)
Date: 9 Mar 1994 09:48:54 -0600
Organization: PowerTools, Austin, TX
In article <1994Mar6.013005.18429@afterlife.ncsc.mil>,
M. Scott Smith <mssmith@afterlife.ncsc.mil> wrote:
> One of the other things that has been eating at me is the best way to
>handle "timing." The best method will be to make the animation machine-
>independent. If a sprite is moving across the screen at a certain speed
>on the PowerMac's, it should move at the same speed on an LC. This may
>mean skipping frames in the animation -- or moving the sprite along 4
>pixels at a time instead of 2.
>
> I've mulled over this one a bit, but haven't come up with anything
>that I'm particularly thrilled about. Any suggestions?
Sorry about the funky From: line; this is really Al Evans (al@crucible.
powertools.com), posting from an alternate site because my newsfeed
has been hosed for the past few days.
Anyway: Let's take a simple case. There is an "overall" animation system
time. Each sprite has variables which represent its move interval and
its last move time. For each frame, you run through the sprite list and
update the sprites for which lastMove + moveInterval <= currentTime.
At this point, you have three options. First, you can set the sprite's
last move time to the current system time. The advantage of this approach
is that each frame gets drawn for each sprite. The disadvantage is that,
on entry, currentTime can easily be lastMove + (10 * moveInterval),
and the extra nine moveIntervals are lost forever. In other words, unless
the host system is fast enough that the maximum animation time is less
than the minimum move interval, the animation will slow down.
The second approach is to do something like
while ((lastMove + moveInterval) <= currentTime) {
MoveSprite(thisSprite);
lastMove = lastMove + moveInterval;
}
This keeps the sprite movement speeds the same on all systems, but leads
to skipped frames (and possible jerky animation) on slower systems. In
addition, you must provide some means of "stopping the clock" when
you are not animating. For example, if the user holds down a menu so that
your animation loop doesn't get called for a few seconds, the sprites
will all jump to where they are supposed to be "now" if the clock has
continued running.
Finally, you can combine the two approaches, setting last move equal
to lastMove + moveInterval but only moving once each time through the
loop. This assumes that there will be time available at some point for
the animation to "catch up" on comparatively slow systems (for example,
a series of frames in which most sprites are standing still). With this
technique, all sprites will be where they are supposed to be -- eventually.
The problem of stopping time while the user holds down a menu (or whatever)
remains, only in this case the sprites will "run real fast" to get
where they're supposed to be when the user releases the menu.
I am not really satisfied with any of these approaches, but the only
better one I can think of is to measure system speed and alter the
move distances (and frame changes) of each sprite, possibly using
fixed-point numbers for fractional pixels. If anybody has a better method,
I'd like to hear it.
For a variety of reasons, I personally use the first method, and
accept the inevitable slowdown on slower systems.
--Al Evans--
+++++++++++++++++++++++++++
>From alex@metcalf.demon.co.uk (Alex Metcalf)
Date: Wed, 9 Mar 1994 18:26:03 GMT
Organization: Demon Internet
In article <Arsenault_C-080394123530@134.33.101.226>,
Arsenault_C@msm.cdx.mot.com (Chris Arsenault) wrote:
> In article <alex-060394231343@metcalf.demon.co.uk>,
> alex@metcalf.demon.co.uk (Alex Metcalf) wrote:
>
> > That's all fine and well, but if your game doesn't have an event loop
> > (as most arcade games don't, since it takes too much CPU time for
> > background processing), there's nothing else to do while you're waiting for
> > the next animation interval!
>
> One of the things I do is to switch in and out of a main event loop. When
> running time critical game code I stay out of the main event loop, working
> only with specific keypresses etc. When I see a special key (such as the
> space bar) I switch in and out of the main event loop where I handle events
> normally. The nice part about this approach is I have very clean/fast
> animation without background process relinquish jitters, but I can still
> handle menus, application switching and the like.
>
> BTW, when you're the foreground process you can tell the system that you
> really want all the time you can by setting the WaitNextEvent sleep
> parameter to 0.
Interesting.... I already have an event loop for other parts of the
game (such as loading and intro), but I hadn't considered sharing my
important game code time with other events. Worth a try!
Alex
+++++++++++++++++++++++++++
>From ua025@freenet.Victoria.BC.CA (Cody Jones)
Date: Thu, 10 Mar 1994 08:58:39 GMT
Organization: The Victoria Freenet Association (VIFA), Victoria, B.C., Canada
I posted my method of handling animation-rates on different systems some
time ago. Others have posted similar ideas and some think that it would
be wise to use Time Manager tasks to handle movement. There is no need -
to avoid having movement be integer-multiples of the update-frequency,
simply store your velocity and positions as fixed point. In my present
project I use 10.6 bits. I have a routine that converts a fixed-pt.
coordinate and two lengths into a rectangle; this is used for any
memory-copying or intersection-testing.
Personally I think doing it this way is better than setting up a Time
Manager task for every moving object.
Cody Jones
Zerius Development
--
+++++++++++++++++++++++++++
>From s_heidri@ira.uka.de (Dietmar Heidrich)
Date: 10 Mar 1994 18:12:58 GMT
Organization: University of Karlsruhe, Comp. Sc. Dept., FRG
Chris Arsenault (Arsenault_C@msm.cdx.mot.com) wrote:
: In article <2lfbu7INN597@iraun1.ira.uka.de>, s_heidri@iraul1.ira.uka.de
: (Dietmar Heidrich) wrote:
: > I am no Mac programmer, but on other platforms you can switch video buffers
: > for games instead of copying everything you already have drawn. Is there
: > no way to do that OS compliant on the Mac ? I think CopyBits() will be too
: > slow for action games if you need to copy 640x480x8bit = 307200 bytes per
: > frame. For 30 frames/s update rate, this yields 9 MB/s transfer rate eaten
: > up only for CopyBits(). Assuming you can transfer 16 bytes via burst (giving
: > 576000 bursts needed) in 20 clock cycles, this means 46% CPU time on a 25 MHz
: > 68040.
: Actually, there is a tradeoff involved. By using CopyBits we gain
: simplicity in handling numerous video configurations and application
: longevity. What we lose is speed. We don't have a mode 13h or X. If we
: draw using Toolbox trap calls to memory on a video card, then we have to
: run over NuBus. (number of draw calls * (Trap dispatch overhead + NuBus
: overhead + actual operation) = too expensive).
What is mode 13h ? I think you assume I am an Intel-Weirdo. I AM NOT !
But you can design hardware-independant systems with double-buffering and
OS compliancy. You do not have to lose speed. And as long as the system
provides fast BitBlt() for the graphics board memory, the NuBus should not
be an obstacle.
Dietmar Heidrich
+++++++++++++++++++++++++++
>From dwareing@apanix.apana.org.au (David Wareing)
Date: 11 Mar 94 04:18:24 GMT
Organization: Apanix Public Access Unix, +61 8 373 5485 (5 lines)
mgleason@cse.unl.edu (Mike Gleason) writes:
>|s_heidri@iraul1.ira.uka.de (Dietmar Heidrich) wrote:
>|> I am no Mac programmer, but on other platforms you can switch video buffers
>|> for games instead of copying everything you already have drawn. Is there
>|> no way to do that OS compliant on the Mac ?
>|Nope.
>That's pretty depressing. The Sega Genesis and Commodore Amiga, which
>use the same damn 68000 in the Mac Plus I use, get phemomenal performance.
Yeah, I wonder why. Can you say "custom blitting hardware"? Decent graphic
performance is expected from both the Sega Genesis/MegaDrive and the
Amiga, as both started out life as games machines (both still are, but I
digress). The did not start their lives as multi-purpose home and business
computers. They do one job and they do it well. Want to try and run Word
or Lotus 123 on a Sega games machine? Of course not - games boxes weren't
designed to do such things. Just as the Mac Plus was not designed to play
Sonic the Hedgehog.
>Ever play Sonic the Hedgehog? That should be able to be done on a mac.
>Hard to believe...
*Very* hard to believe actually. Why should it be able to done on a mac?
Somehow I don't think the number one choice for buying a mac is its
ability to play Sonic. I agree that macs should eventually come standard
with some form of hardware-accelerated graphics, but lets not get carried
away and whine that you can't play Sonic on a lowly Mac Plus.
>I think the Amiga uses a Screen pointer, which is
>changeable by the programmer, so that to do very fast screen scrolling,
>all you need to do is set the screen pointer to something else. It makes
>no sense to me that you have to re-copy the whole damn screen if all you
>want to do is scroll the screen downward a pixel.
See the comments above about the Amiga's blitting hardware. Damn it.
Horses for courses.
--
David Wareing
Adelaide, South Australia
Mac Games & Multimedia Programming dwareing@apanix.apana.org.au
- --------------------------------------------------------------------
+++++++++++++++++++++++++++
>From snozer@cats.ucsc.edu (Daniel Craig Jalkut)
Date: 14 Mar 1994 08:22:55 GMT
Organization: University of California, Santa Cruz
In <dwareing.763359504@apanix.apana.org.au> dwareing@apanix.apana.org.au (David Wareing) writes:
>Yeah, I wonder why. Can you say "custom blitting hardware"? Decent graphic
>performance is expected from both the Sega Genesis/MegaDrive and the
>Amiga, as both started out life as games machines (both still are, but I
>digress). The did not start their lives as multi-purpose home and business
>computers. They do one job and they do it well. Want to try and run Word
>or Lotus 123 on a Sega games machine? Of course not - games boxes weren't
>designed to do such things. Just as the Mac Plus was not designed to play
>Sonic the Hedgehog.
But the bottom line is that the Amiga can do everything the Mac can
do, but the converse is not true. The advantages you point out for
the Mac are all software(which is why i'm a mac user and no longer an
Amigan), if the software were written as well for the Amiga(including
the OS), then you'd have the equivalent of a Macintosh with the bonus
of excellent graphics hardware. And the Amiga computers were sold
for much less than macs in the past, so it's not infeasable cost-wise
that the Macs have this type of hardware for graphics.
Would be nice...
+++++++++++++++++++++++++++
>From rba26@cas.org (Brad Andrews)
Date: Mon, 14 Mar 1994 18:08:22 GMT
Organization: Chemical Abstracts Service
In article dpi@darkstar.UCSC.EDU, snozer@cats.ucsc.edu (Daniel Craig Jalkut) writes:
]
]But the bottom line is that the Amiga can do everything the Mac can
]do, but the converse is not true. The advantages you point out for
Hardly. Certainly you may prefer the Amiga, and many do, but some things are
extremely difficult. I had a lot more hastles getting an Amiga version of
a game port running than I did on the Mac, including such things as supporting a
hard drive.
- -
Brad Andrews
brad.andrews@cas.org
All opinions are strictly mine
+++++++++++++++++++++++++++
>From snozer@cats.ucsc.edu (Daniel Craig Jalkut)
Date: 15 Mar 1994 16:03:41 GMT
Organization: University of California, Santa Cruz
In <1994Mar14.180822.7882@chemabs.uucp> rba26@cas.org (Brad Andrews) writes:
>Hardly. Certainly you may prefer the Amiga, and many do, but some things are
>extremely difficult. I had a lot more hastles getting an Amiga version of
>a game port running than I did on the Mac, including such things as supporting a
>hard drive.
If I preferred Amigas, I wouldn't have said that I was a mac person.
+++++++++++++++++++++++++++
>From s_heidri@irau32.ira.uka.de (Dietmar Heidrich)
Date: 17 Mar 1994 13:36:48 GMT
Organization: University of Karlsruhe, FRG
In article <dwareing.763359504@apanix.apana.org.au>, dwareing@apanix.apana.org.au (David Wareing) writes:
|> mgleason@cse.unl.edu (Mike Gleason) writes:
|>
|> >|s_heidri@iraul1.ira.uka.de (Dietmar Heidrich) wrote:
|>
|> >|> I am no Mac programmer, but on other platforms you can switch video buffers
|> >|> for games instead of copying everything you already have drawn. Is there
|> >|> no way to do that OS compliant on the Mac ?
|>
|> >|Nope.
|>
|> >That's pretty depressing. The Sega Genesis and Commodore Amiga, which
|> >use the same damn 68000 in the Mac Plus I use, get phemomenal performance.
|>
|> Yeah, I wonder why. Can you say "custom blitting hardware"? Decent graphic
|> performance is expected from both the Sega Genesis/MegaDrive and the
|> Amiga, as both started out life as games machines (both still are, but I
|> digress). The did not start their lives as multi-purpose home and business
|> computers. They do one job and they do it well. Want to try and run Word
|> or Lotus 123 on a Sega games machine? Of course not - games boxes weren't
|> designed to do such things. Just as the Mac Plus was not designed to play
|> Sonic the Hedgehog.
I did not ask for special-purpose hardware, I was asking about opening and
switching two video buffers. To me, this purely seems to be a question of
programming interface. The MacOS does not support this (though it would be
quite simple to implement that), so the game programming idea I had is dead.
--
Dietmar Heidrich, Universitaet Karlsruhe, Germany
"Die Hoffnung auf den Tod ist das einzige, was mich am Leben erhaelt."
+++++++++++++++++++++++++++
>From fixer@faxcsl.dcrt.nih.gov (Chris Gonna' Find Ray Charles Tate)
Date: Thu, 17 Mar 1994 16:15:36 GMT
Organization: DCRT, NIH, Bethesda, MD
In article <2m9mdgINNei4@iraun1.ira.uka.de>, s_heidri@irau32.ira.uka.de (Dietmar Heidrich) writes:
>
>I did not ask for special-purpose hardware, I was asking about opening and
>switching two video buffers. To me, this purely seems to be a question of
>programming interface. The MacOS does not support this (though it would be
>quite simple to implement that), so the game programming idea I had is dead.
But video double-buffering *is* dependant on the hardware.
Think about it - you need to be able to tell the video card where to look
in RAM for its frame buffer. That sounds like hardware functionality to
me....
I *believe* the original Apple color video card (that they would sell you
with a Mac II) supported two switchable frame buffers in 16-color mode.
You switched between them with a Control() call to the video driver, as
I recall. I also think that Vette! (or some other driving game?) used
this capability.
Unfortunately, it's not a guaranteed availability by any stretch of the
imagination, and so you can't write code depending on it. I agree that
it would be nice to have hardware pan, though, as a documented and
required video card capability. That's the one that's the most expensive
to do in software. Makes the idea of a 'Xevious' clone pretty remote. :-)
- --------------------------------------------------------------------------
Christopher Tate | "I hate writing, and I hate statistics, but
MSD, Inc. | most of all I hate writing about statistics.
| I'd rather go to the dentist; at least there
fixer@faxcsl.dcrt.nih.gov | you get to spit." -- Ed Sewell
+++++++++++++++++++++++++++
>From Pascal_Haakmat
Date: Mon, 14 Mar 94 20:09:46 +0100
Organization: (none)
>That's pretty depressing. The Sega Genesis and Commodore Amiga
DW> Horses for courses.
Nonetheless, it remains pretty depressing.
Pascal.
- - Obolus 1.0.2
* Origin: pretty blue dreams (2:281/202.13)
---------------------------
>From peirce@outpost.SF-Bay.org (Michael Peirce)
Subject: System Folder on NONstartup disk
Date: Thu, 3 Mar 94 19:51:03 PST
Organization: Peirce Software, Inc.
Does anyone know how to find the System Folder on a volume that isn't
the startup volume?
-- Michael Peirce -- peirce@outpost.sf-bay.org
-- Peirce Software, Inc. -- 719 Hibiscus Place, Suite 301
-- -- San Jose, California USA 95117
-- Makers of: Smoothie & -- voice: +1.408.244.6554 fax: +1.408.244.6882
-- Peirce Print Tools -- AppleLink: peirce & America Online: AFC Peirce
+++++++++++++++++++++++++++
>From mxmora@unix.sri.com (Matt Mora)
Date: 4 Mar 1994 09:42:08 -0800
Organization: SRI International, Menlo Park, CA
In article <CNjbKKKX.pns11u@outpost.SF-Bay.org> peirce@outpost.SF-Bay.org
(Michael Peirce) writes:
>Does anyone know how to find the System Folder on a volume that isn't
>the startup volume?
Are you talking about a volume that has a system folder that's not blessed?
If its not blessed you probably need to do a PBCatSearch.
If its blessed, but not the startup volume, I assume you call findfolder
with the vRefNum set to the vRefnum of the volume that you want to
look on. Being that you're Michael Peirce, you probably already
tried that it it doesn't work. In that case do scan of the disk
and look for a folder that contains the finder and system at the same level
and you have a good chance that those files parent directory is/was
a system folder.
Xavier
P.S. Are you setting up another netter's dinner?
--
___________________________________________________________
Matthew Xavier Mora Matt_Mora@qm.sri.com
SRI International mxmora@unix.sri.com
333 Ravenswood Ave Menlo Park, CA. 94025
+++++++++++++++++++++++++++
>From Robin J. Lunge <rjl1@cornell.edu>
Date: 5 Mar 1994 03:36:41 GMT
Organization: Cornell University
In article <CNjbKKKX.pns11u@outpost.SF-Bay.org> Michael Peirce,
peirce@outpost.SF-Bay.org writes:
>Does anyone know how to find the System Folder on a volume that isn't
>the startup volume?
FindFolder ought to work on any startup disk -- whether it is the current
startup disk or not. If you are talking about a disk that is not blessed,
the only solution is to search for a folder containing a "Finder" and a
"System" (use PBCatSearch if it is available). The Finder and System
strings are script-independent.
+++++++++++++++++++++++++++
>From Ron_Hunsinger@bmug.org
Date: Sat, 05 Mar 1994 19:39:48 -0700
Organization: BMUG, Inc.
Michael Peirce,peirce@outpost.SF-Bay.org writes:
>Does anyone know how to find the System Folder on a volume that isn't
>the startup volume?
Its directoryID is the first longword of vcbFndrInfo. This isn't
documented anywhere, but I don't see how they can change it, since
the ROM has to be getting the system folder from here at bootup.
-Ron Hunsinger
+++++++++++++++++++++++++++
>From macguru@halcyon.com. (Allan Foster)
Date: 10 Mar 1994 07:08:02 GMT
Organization: Guru Inc
In article <1994Mar05.193948.1193292@bmug.org>
Ron_Hunsinger@bmug.org writes:
> Michael Peirce,peirce@outpost.SF-Bay.org writes:
>
> >Does anyone know how to find the System Folder on a volume that isn't
> >the startup volume?
>
> Its directoryID is the first longword of vcbFndrInfo. This isn't
> documented anywhere, but I don't see how they can change it, since
> the ROM has to be getting the system folder from here at bootup.
>
Except that I do not believe that the rom gets this information...
That is all done by the boot blocks... just my $0.02 nitpicking!
Allan Foster
- --------------------------------------------------------
I am responsible for what I say and do. -- Allan Foster --
---------------------------
>From "Andrew C. Plotkin" <ap1i+@andrew.cmu.edu>
Subject: Trap dispatcher overhead
Date: Tue, 1 Mar 1994 19:23:18 -0500
Organization: Information Technology Center, Carnegie Mellon, Pittsburgh, PA
Every few days, a post floats by here saying "Don't call toolbox traps
in time-critical loops; they take forever." How long is forever? I mean,
is there a nice rule like "a trap dispatch is worth 27 pointer
dereferences on a '030 CPU"?
What about "idiot" toolbox calls (like SetRectSize or OffsetRect, that
would be blindingly fast if compiled inline)? Is is worth #defining
macros to replace them, or do the header files take care of this? (I'd
look, but I'm not at my Mac right now.) (Think C 5.0.4 header files, if
it matters.)
And, most importantly :-) why doesn't Inside Macintosh tell you about
this? I originally assumed that a toolbox call was as fast as any other
function call, with maybe a couple of memory lookups and register loads
tacked on.
--Z
"And Aholibamah bare Jeush, and Jaalam, and Korah: these were the borogoves..."
+++++++++++++++++++++++++++
>From resnick@cogsci.uiuc.edu (Pete Resnick)
Date: Wed, 02 Mar 1994 00:09:17 -0600
Organization: University of Illinois at Urbana-Champaign
In article <MhQxlq600gpI0WyHdn@andrew.cmu.edu>, "Andrew C. Plotkin"
<ap1i+@andrew.cmu.edu> wrote:
>Every few days, a post floats by here saying "Don't call toolbox traps
>in time-critical loops; they take forever." How long is forever? I mean,
>is there a nice rule like "a trap dispatch is worth 27 pointer
>dereferences on a '030 CPU"?
Examples: On the original 68000, the trap itself takes 34 clock cycles. On
the 68030, it takes 18-20 cycles. The trap dispatcher takes some amount of
time to figure out what routine to call for an individual trap word, so
you would have to add on the time it takes to go through a small search.
Then the RTE is 20 cycles on the 68000, or 18-20 cycles on the 68030. So
altogether, we're probably talking about something on the order of a
divide instruction. That's a good chunk of overhead for silly things like
SetRect, but not bad at all for other things.
pr
--
Pete Resnick (...so what is a mojo, and why would one be rising?)
Graduate assistant - Philosophy Department, Gregory Hall, UIUC
System manager - Cognitive Science Group, Beckman Institute, UIUC
Internet: resnick@cogsci.uiuc.edu
+++++++++++++++++++++++++++
>From ari@world.std.com (Ari I Halberstadt)
Date: Sat, 5 Mar 1994 11:11:29 GMT
Organization: The World Public Access UNIX, Brookline, MA
In article <MhQxlq600gpI0WyHdn@andrew.cmu.edu>,
Andrew C. Plotkin <ap1i+@andrew.cmu.edu> wrote:
>Every few days, a post floats by here saying "Don't call toolbox traps
>in time-critical loops; they take forever." How long is forever? I mean,
>is there a nice rule like "a trap dispatch is worth 27 pointer
>dereferences on a '030 CPU"?
If speed of execution is truly critical then you're better off not
using a Toolbox trap. For instance, context switches for threads
should be very efficient. In my Thread Library (a publicly available
implementation of nonpreemptive threads), threads are scheduled for
execution at a certain time. I wanted to reduce the time spent in
context switches, and since the scheduling loop was already pretty
minimal I substituted the use of the TickCount trap with a direct
access to the Ticks low-memory global. This resulted in nearly a 50%
decrease in the time spent in scheduling context switches. Apple's
Thread Manager is slower than Thread Library. I suspect that, at least
in part, the slowness of Apple's Thread Manager is due to its use of
traps.
You should, however, take great pains to use documented traps to
access the operating system. Before using the Ticks low-memory global,
I tried calling the TickCount trap only once. Instead of something
like the following:
for (each thread) {
if (TickCount() - thread->went_to_sleep >= thread->sleep_time)
activate this thread;
}
you could cache the value of TickCount, assuming the inner loop would
execute in less than 1 tick (a valid assumption for many operations).
unsigned long ticks;
ticks = TickCount();
for (each thread) {
if (ticks >= thread->time_to_wakeup) // we precalculated time_to_wakeup
activate this thread;
}
Only if this is not feasible (because the loop takes too long), or is
still too slow, should you use the Ticks low-memory global.
--
Ari Halberstadt ari@world.std.com #include <std/disclaimer.h>
"These beetles were long considered to be very rare because very few
entomologists look for beetles in the mountains, in winter, at night,
during snow storms." -- Purves W. K., et al, "Life: The Science of
+++++++++++++++++++++++++++
>From "Andrew C. Plotkin" <ap1i+@andrew.cmu.edu>
Date: Wed, 9 Mar 1994 11:45:19 -0500
Organization: Information Technology Center, Carnegie Mellon, Pittsburgh, PA
In article <MhQxlq600gpI0WyHdn@andrew.cmu.edu>,
Andrew C. Plotkin <ap1i+@andrew.cmu.edu> wrote:
>Every few days, a post floats by here saying "Don't call toolbox traps
>in time-critical loops; they take forever." How long is forever? I mean,
>is there a nice rule like "a trap dispatch is worth 27 pointer
>dereferences on a '030 CPU"?
A small experiment (what, facts on the Net?) has determined that calling
the SetRect trap takes about -four times- the time of the equivalent
four assignment statements.
Parameters:
'040 CPU, Centris 610
virtual memory off, 32-bit mode off
Think C 5.0.4, no optimization
A loop which just calls SetRect (or the equivalent macro) 10^n times,
same arguments each time, none of the arguments equal to zero. (Yes, I
disassembled the code and made sure it wasn't sneakily optimizing
anything away behind my back.)
The object size difference was a few bytes (four or six, I think), which
is unlikely to be a big deal.
So I put SetRect and SetPt macros into my project. And immediately it
stopped working right. Sigh. Turned out I had two calls of the form
SetRect(&box, x, y, x+box.right-box.left, y+box.bottom-box.top);
and changing the function call to a macro changed the semantics! Heh. Be
warned.
Conclusion: it's worthwhile, but be careful. And in C++ you probably
want to declare an inline function rather than a macro.
--Z
"And Aholibamah bare Jeush, and Jaalam, and Korah: these were the borogoves..."
+++++++++++++++++++++++++++
>From macguru@halcyon.com. (Allan Foster)
Date: 10 Mar 1994 07:12:12 GMT
Organization: Guru Inc
In article <whTToTS00gpIFYYFsM@andrew.cmu.edu>
"Andrew C. Plotkin" <ap1i+@andrew.cmu.edu> writes:
> In article <MhQxlq600gpI0WyHdn@andrew.cmu.edu>,
> Andrew C. Plotkin <ap1i+@andrew.cmu.edu> wrote:
> >Every few days, a post floats by here saying "Don't call toolbox traps
> >in time-critical loops; they take forever." How long is forever? I mean,
> >is there a nice rule like "a trap dispatch is worth 27 pointer
> >dereferences on a '030 CPU"?
>
> A small experiment (what, facts on the Net?) has determined that calling
> the SetRect trap takes about -four times- the time of the equivalent
> four assignment statements.
>
The trap dispatcher overhead is in the order of 120 Cycles, depending
on the machine, and which trap you are calling.... I believe that
toolbox traps take slightly longer, (140?? cycles)
It is a fact that the trivial traps should rather be coded inline.
These being SetPt, EqualPt and even the Rect calls should be inline.
In fact, I believe that the new MPW glue libraries actually implement
some these functions as glue rather than the trap call....
For most other traps, the overhead of the dispatcher becomes
insignificant.
Allan Foster
- --------------------------------------------------------
I am responsible for what I say and do. -- Allan Foster --
+++++++++++++++++++++++++++
>From sigurasg@rhi.hi.is (Sigurdur Asgeirsson)
Date: 10 Mar 1994 14:47:33 GMT
Organization: University of Iceland
In <2lmh8c$5l4@nwfocus.wa.com> macguru@halcyon.com. (Allan Foster) writes:
>In article <whTToTS00gpIFYYFsM@andrew.cmu.edu>
>"Andrew C. Plotkin" <ap1i+@andrew.cmu.edu> writes:
>> In article <MhQxlq600gpI0WyHdn@andrew.cmu.edu>,
>> Andrew C. Plotkin <ap1i+@andrew.cmu.edu> wrote:
>> >Every few days, a post floats by here saying "Don't call toolbox traps
[snip]
>>
>The trap dispatcher overhead is in the order of 120 Cycles, depending
>on the machine, and which trap you are calling.... I believe that
>toolbox traps take slightly longer, (140?? cycles)
When virtual memory is enabled you get some additional overhead.
Basically what happens is that the a-trap traps to supervisory level via
the VBR trap vector, then there's a shift back down to user level, and
a jump to the original lomem trap vector. I sometimes wonder if this
additional a-trap overhead is the main cause for the apparent slowdown
when VM is on.
--
Sigurdur Asgeirsson | "Well you know, C isn't that hard, void (*(*f[])())()
Kambasel 26 | for instance declares f as an array of unspecified
109 Reykjavik, Iceland | size, of pointers to functions that return pointers to
sigurasg@rhi.hi.is | functions that return void... I think"
+++++++++++++++++++++++++++
>From platypus@cirrus.som.cwru.edu (Gary Kacmarcik)
Date: 10 Mar 1994 18:58:48 GMT
Organization: Case Western Reserve University, Cleveland, Ohio (USA)
In article <2lmh8c$5l4@nwfocus.wa.com> macguru@halcyon.com. (Allan Foster) writes:
> In article <whTToTS00gpIFYYFsM@andrew.cmu.edu>
> "Andrew C. Plotkin" <ap1i+@andrew.cmu.edu> writes:
> >
> > A small experiment (what, facts on the Net?) has determined that calling
> > the SetRect trap takes about -four times- the time of the equivalent
> > four assignment statements.
>
> The trap dispatcher overhead is in the order of 120 Cycles, depending
> on the machine, and which trap you are calling.... I believe that
> toolbox traps take slightly longer, (140?? cycles)
>
> It is a fact that the trivial traps should rather be coded inline.
> These being SetPt, EqualPt and even the Rect calls should be inline.
last night i wrote a program which takes a PEF application as input and
modifies the app so that all calls to SetRect and SetPt are made "inline".
(well, OK, i had written all of the PEF parsing stuff earlier, i just
had to modify it to scan for and modify these routines).
it does this by replacing the 6-instruction global linkage for the routine
with an implementation of the routine itself. this can be done for any
routine that can be implemented in 5 (or fewer) PowerPC instructions.
basically, i convert: into:
glink: lwz r12,xx(r2) subic r3,r3,2
stw r2,0x14(r1) sthu r5,2(r3)
lwz r0,0x0(r12) sthu r4,2(r3)
lwz r2,0x4(r12) sthu r7,2(r3)
mtctr r0 sthu r6,2(r3)
bctr blr
i haven't tested it yet (since i don't have a PowerMac), but i see
no reason why this shouldn't work. the only "worry" i have is that
it trashes r3 (which contains the ptr to the rect), but since SetRect
doesn't return a value and r3-r10 are volatile, i believe that this
should be OK.
anyway, i can't distribute this yet because of licensing issues that i
have to work out with Apple. i wrote the code, but it's based on some
of Apple's headers -- so i need to make sure that things are OK before
i release it. i'll post it somewhere as soon as these issues are
resolved.
-gary j kacmarcik
platypus@curie.ces.cwru.edu
+++++++++++++++++++++++++++
>From rollin@newton.apple.com (Keith Rollin)
Date: Sun, 13 Mar 1994 01:42:44 GMT
Organization: Apple Computer, Inc.
In article <whTToTS00gpIFYYFsM@andrew.cmu.edu>, "Andrew C. Plotkin"
<ap1i+@andrew.cmu.edu> wrote:
> In article <MhQxlq600gpI0WyHdn@andrew.cmu.edu>,
> Andrew C. Plotkin <ap1i+@andrew.cmu.edu> wrote:
> >Every few days, a post floats by here saying "Don't call toolbox traps
> >in time-critical loops; they take forever." How long is forever? I mean,
> >is there a nice rule like "a trap dispatch is worth 27 pointer
> >dereferences on a '030 CPU"?
>
> A small experiment (what, facts on the Net?) has determined that calling
> the SetRect trap takes about -four times- the time of the equivalent
> four assignment statements.
>
> Parameters:
> '040 CPU, Centris 610
> virtual memory off, 32-bit mode off
> Think C 5.0.4, no optimization
> A loop which just calls SetRect (or the equivalent macro) 10^n times,
> same arguments each time, none of the arguments equal to zero. (Yes, I
> disassembled the code and made sure it wasn't sneakily optimizing
> anything away behind my back.)
>
> The object size difference was a few bytes (four or six, I think), which
> is unlikely to be a big deal.
>
> So I put SetRect and SetPt macros into my project. And immediately it
> stopped working right. Sigh. Turned out I had two calls of the form
> SetRect(&box, x, y, x+box.right-box.left, y+box.bottom-box.top);
> and changing the function call to a macro changed the semantics! Heh. Be
> warned.
>
> Conclusion: it's worthwhile, but be careful. And in C++ you probably
> want to declare an inline function rather than a macro.
And after you started using the macros, was there any discernable
difference in the execution speed of your program? Was there any measurable
difference in the speed of your program?
I want to thank you for actually performing the experiment and seeing what
the effect of the trap dispatcher has on small functions like SetRect and
SetPt. But before a "ban calling through the trap dispatcher" campaign gets
started, I want to highlight two things:
1) The overhead of the trap dispatcher is negligable for most calls. For
instance, it would be interesting to see what measurable difference there
is in calling LineTo via the trap dispatcher and calling it directly (after
a GetTrapAddress call).
2) Even when there is a measurable difference, is there an _apparent_
difference? Is it worth the hassle and compatibility problems of
re-implementing system functionality inline or calling a system function
directly?
- --------------------------------------------------------------------------
Keith Rollin --- Phantom Programmer --- Apple Computer, Inc. --- Team
Newton
+++++++++++++++++++++++++++
>From mxmora@unix.sri.com (Matt Mora)
Date: 16 Mar 1994 16:32:25 -0800
Organization: SRI International, Menlo Park, CA
In article <rollin-120394174244@rollin-keith.apple.com> rollin@newton.apple.com (Keith Rollin) writes:
>2) Even when there is a measurable difference, is there an _apparent_
>difference? Is it worth the hassle and compatibility problems of
>re-implementing system functionality inline or calling a system function
>directly?
The original thread was about doing his own line drawing by writing
directly to screen. If he didn't care about that incompatibility,
then calling the trap directly is the lesser of the two evils. If your
goal is speed, calling a trap isn't going to help, no matter how
small the overhead.
Xavier
--
___________________________________________________________
Matthew Xavier Mora Matt_Mora@sri.com
SRI International mxmora@unix.sri.com
333 Ravenswood Ave Menlo Park, CA. 94025
---------------------------
>From jclark@galaxy.csc.calpoly.edu (Joseph V Clarke)
Subject: User in a menu?
Date: Tue, 08 Mar 94 19:16:35 GMT
Organization: Computer Science Department, Cal Poly SLO
An event is only generated when a menu item has been selected...
So how could I find out if the user is clicking on a menu..
(not neccessarily selecting an item, though.) Can I patch
some kind of interrupt handler? My application is real time
intensive and when someone holds down the menu, my app loses control
of the mac and the real time is lost (the data is crunched and when
I release the menu, it gushes out...thereby not accurately representing
the data.)
I would just like to clear the buffer and eliminate the data if the
user happened to be in the menu for awhile. Suggestions?
Thanks for your time!
Joseph
--
Telemidi - A Mac application that allows 2 musicians to instantaneously express
their musical ideas in real time over the phone lines.
Joseph V. Clarke ===================================== jclark@galaxy.calpoly.edu
+++++++++++++++++++++++++++
>From sw@network-analysis-ltd.co.uk (Sak Wathanasin)
Date: Wed, 9 Mar 94 19:52:17 GMT
Organization: Network Analysis Ltd
In article <1994Mar08.191635.25383@rat.csc.calpoly.edu> (comp.sys.mac.programmer), jclark@galaxy.csc.calpoly.edu (Joseph V Clarke) writes:
> some kind of interrupt handler? My application is real time
> intensive and when someone holds down the menu, my app loses control
> of the mac and the real time is lost (the data is crunched and when
> I release the menu, it gushes out...thereby not accurately representing
> the data.)
>
> I would just like to clear the buffer and eliminate the data if the
> user happened to be in the menu for awhile. Suggestions?
Try using a MenuHook proc: see Inside Mac vol 1 pg 356.
Sak Wathanasin
Network Analysis Limited
178 Wainbody Ave South, Coventry CV3 6BX, UK
Internet: sw@network-analysis-ltd.co.uk
uucp: ...!uknet!nan!sw AppleLink: NAN.LTD
Phone: (+44) 203 419996 Mobile:(+44) 850 587411 Fax: (+44) 203 690690
+++++++++++++++++++++++++++
>From paulr@syma.sussex.ac.uk (Paul Russell)
Date: Thu, 10 Mar 1994 14:41:27 GMT
Organization: University of Sussex
Sak Wathanasin (sw@network-analysis-ltd.co.uk) wrote:
: In article <1994Mar08.191635.25383@rat.csc.calpoly.edu> (comp.sys.mac.programmer), jclark@galaxy.csc.calpoly.edu (Joseph V Clarke) writes:
: > some kind of interrupt handler? My application is real time
: > intensive and when someone holds down the menu, my app loses control
: > of the mac and the real time is lost (the data is crunched and when
: > I release the menu, it gushes out...thereby not accurately representing
: > the data.)
: >
: > I would just like to clear the buffer and eliminate the data if the
: > user happened to be in the menu for awhile. Suggestions?
: Try using a MenuHook proc: see Inside Mac vol 1 pg 356.
I wrote a little background tasking unit for a comms program a
few years back and I spent some time working out which traps
needed to be patched in order to get regular calls regardless
of what the user is doing.
It turns out that you can do this by patching two traps - GetNextEvent and
OSEventAvail (I think). GetNextEvent gets called most of the time and
OSEventAvail gets called when the mouse is down in a menu. (BTW,
WaitNextEvent calls GetNextEvent).
You need to make sure that your patches are in the System heap so that
they still get called when your application is switched to the background.
Doing this is much nicer than using VBL's, particularly when it comes
to debugging...
//Paul
--
| Paul Russell | Internet: P.T.Russell@sussex.ac.uk |
| Experimental Psychology | AppleLink: EP.SUSSEX |
| Sussex University, Falmer | Telephone: +44 273 678639 |
| Brighton BN1 9QG, England | Facsimile: +44 273 678433 |
+++++++++++++++++++++++++++
>From dean@genmagic.com (Dean Yu)
Date: 10 Mar 1994 21:46:46 GMT
Organization: General Magic, Inc.
In article <1994Mar08.191635.25383@rat.csc.calpoly.edu>
(comp.sys.mac.programmer), jclark@galaxy.csc.calpoly.edu (Joseph V Clarke)
writes:
> some kind of interrupt handler? My application is real time
> intensive and when someone holds down the menu, my app loses control
> of the mac and the real time is lost (the data is crunched and when
> I release the menu, it gushes out...thereby not accurately representing
> the data.)
>
> I would just like to clear the buffer and eliminate the data if the
> user happened to be in the menu for awhile. Suggestions?
Assuming that this is an application of your own creation, and you're not
using some application framework, you know when the user started mousing
around in a menu because you called MenuSelect, and you know when the user
let go of the button because MenuSelect returns.
-- Dean Yu
Negative Ethnic Role Model
General Magic, Inc.
+++++++++++++++++++++++++++
>From KLUEV@jonathan.srcc.msu.su
Date: Sat, 12 Mar 1994 21:14:18 +0300
Organization: (none)
In article <1994Mar10.144127.15078@syma.sussex.ac.uk>
paulr@syma.sussex.ac.uk (Paul Russell) writes:
>Sak Wathanasin (sw@network-analysis-ltd.co.uk) wrote:
>
>: In article <1994Mar08.191635.25383@rat.csc.calpoly.edu> (comp.sys.mac.programmer), jclark@galaxy.csc.calpoly.edu (Joseph V Clarke) writes:
>: > some kind of interrupt handler? My application is real time
>: > intensive and when someone holds down the menu, my app loses control
>: > of the mac and the real time is lost (the data is crunched and when
>: > I release the menu, it gushes out...thereby not accurately representing
>: > the data.)
>: Try using a MenuHook proc: see Inside Mac vol 1 pg 356.
>
>I wrote a little background tasking unit for a comms program a
>few years back and I spent some time working out which traps
>needed to be patched in order to get regular calls regardless
>of what the user is doing.
>
>It turns out that you can do this by patching two traps - GetNextEvent and
>OSEventAvail (I think). GetNextEvent gets called most of the time and
>OSEventAvail gets called when the mouse is down in a menu. (BTW,
>WaitNextEvent calls GetNextEvent).
>
>You need to make sure that your patches are in the System heap so that
>they still get called when your application is switched to the background.
This "system heapness" works only with VBL's, i.e. if your VBL proc
resides in sysHeap, it (proc) will not be swapped on MF switch.
This trick will not work with patching traps.
It is "near" to be impossible to make a global patch from within an
application, so you need an INIT; and if you want not an INIT but
an application - you need VBL (or other int. time)
Why "near"? One can install a TM or VBL task and patch the trap
for currently running application. Red banner.
Michael Kluev.
---------------------------
>From jfinete@cats.ucsc.edu (Joseph Manuel Finete)
Subject: What happens if my Vertical Retrace task takes too long?
Date: 3 Mar 1994 01:33:00 GMT
Organization: University of California; Santa Cruz
My understanding of the vertical retrace manager is that you supply an
number of ticks to wait before calling the vertical retrace task, and that
your task function should update this number when it's finished.
My question is, if my task takes longer than one tick (1/60 th of a
second) will the number of ticks between tasks be the number of ticks
to complete the task plus the number of interval ticks? Is there any
danger in having a vertical retrace task that can't be completed in one
tick?
--
Joe Finete
jfinete@cats.ucsc.edu
+++++++++++++++++++++++++++
>From ari@world.std.com (Ari I Halberstadt)
Date: Thu, 3 Mar 1994 06:40:51 GMT
Organization: The World Public Access UNIX, Brookline, MA
In article <2l3eoc$k6q@darkstar.ucsc.edu>,
>My understanding of the vertical retrace manager is that you supply an
>number of ticks to wait before calling the vertical retrace task, and that
>your task function should update this number when it's finished.
That's true.
>My question is, if my task takes longer than one tick (1/60 th of a
>second) will the number of ticks between tasks be the number of ticks
>to complete the task plus the number of interval ticks? Is there any
>danger in having a vertical retrace task that can't be completed in one
>tick?
You definitely don't want your task to take longer than 1/60th of a
second. In fact, you want it to take substantially less than 1/60th of
a second, since there are bound to be other tasks the processor has to
handle. If your task takes too long all sorts of things will get
messed up, including cursor tracking, the Ticks low-memory global,
other VBL tasks that need to be executed every 1/60th of a second,
video updates etc. The CPU can accomplish quite a bit of processing in
a fraction of 1/60th of a second. If your task is that compute
intensive you should probably run it during null event processing.
For precise intervals between tasks you should investigate the
extended time manager, though even that won't work well if tasks take
too long. I've found that time manager tasks on a Mac Plus work ok up
to about 1/100th of a second, more frequent than that and the machine
gets pretty slow; this probably applies to other 68000 machines,
though faster CPUs should be able to handle smaller time slices.
--
Ari Halberstadt ari@world.std.com #include <std/disclaimer.h>
"These beetles were long considered to be very rare because very few
entomologists look for beetles in the mountains, in winter, at night,
during snow storms." -- Purves W. K., et al, "Life: The Science of
---------------------------
>From rang@winternet.mpls.mn.us (Anton Rang)
Subject: When to StripAddress? (was Re: Let's kill 24-bit mode!)
Date: 16 Mar 1994 01:33:27 GMT
Organization: Minnesota Angsters
In article <t-gaul-150394171035@infinity.i-link.com> t-gaul@i-link.com (Troy Gaul) writes:
>There are cases where you must call StripAddress for a program to function
>correctly in all 'modes'. It is possible that you haven't run across them.
One which bit me last year, that I never did find documented....
It's important to call StripAddress() on any value that you pass to
InitZone(). Otherwise, something internal to the memory manager
starts to strip *some* addresses in the zone, but not others, and it
all flies apart....
Other than that, hmm. When you patch traps or change hooks (like
the routines in a GrafPort, or low-memory globals), make sure that you
call StripAddress() first. The system might switch into 32-bit mode
and then call your routine. (I'm sure this happens for very few
cases, but I've seen it cause problems before.)
And, obviously, if you're switching modes yourself. :-)
--
Anton Rang (rang@winternet.mpls.mn.us)
---------------------------
>From AIKEN <INRA000@MUSICB.MCGILL.CA>
Subject: Why can't I have AEs *in* AEs?
Date: Fri, 25 Feb 1994 02:35:52 GMT
Organization: McGill University
For reasons of my own (yes, I am sick and twisted) I am trying to
add an Apple Event to another Apple event as a paramater. My code
looks something like:
**
AppleEvent AEToSend,AEToInclude;
Error=AEPutParamDesc(&AEToSend,keyDirectObject,&AEToInclude);
**
the AE Manager just barfs up a -1703 err, "Wrong descriptor type".
Is this not something I'm supposed to be contemplating, or am I mis-
sing something?
The funny thing is, if I do a AEPutParamPtr like:
Error=AEPutParamPtr(&AEToSend,keyDirectObject,'aevt',
&AEToInclude,sizeof(AppleEvent));
Everything is hunky-dory. However, I'm concerned that this method
does not make a true duplicate of AEToInclude, which will definately
raise hell down the line. This is confusing, however, because both
methods should produce a paramater with the same keyword and descriptor
type, no?
Insights *greatly* appreciated.
Mark Aiken
inra@musicb.mcgill.ca
+++++++++++++++++++++++++++
>From jwbaxter@olympus.net (John W. Baxter)
Date: Fri, 25 Feb 1994 00:43:56 -0800
Organization: Internet for the Olympic Peninsula
In article <24FEB94.23325740.0070@VM1.MCGILL.CA>, AIKEN
<INRA000@MUSICB.MCGILL.CA> wrote:
> For reasons of my own (yes, I am sick and twisted) I am trying to
> add an Apple Event to another Apple event as a paramater. My code
> looks something like:
>
> **
> AppleEvent AEToSend,AEToInclude;
>
> Error=AEPutParamDesc(&AEToSend,keyDirectObject,&AEToInclude);
> **
>
> the AE Manager just barfs up a -1703 err, "Wrong descriptor type".
> Is this not something I'm supposed to be contemplating, or am I mis-
> sing something?
Hmmm...surprising that it's not allowed (although it's also surprising you
want to do this). An Apple Event is almost an AERecord (but not quite).
>
> The funny thing is, if I do a AEPutParamPtr like:
>
> Error=AEPutParamPtr(&AEToSend,keyDirectObject,'aevt',
> &AEToInclude,sizeof(AppleEvent));
Not a good idea.
>
> Everything is hunky-dory. However, I'm concerned that this method
> does not make a true duplicate of AEToInclude, which will definately
> raise hell down the line. This is confusing, however, because both
> methods should produce a paramater with the same keyword and descriptor
> type, no?
No. Look at the AEPutParamPtr again. The third parameter points to an
AppleEvent. If you go back far enough, that's just an AEDesc. A type, and
a handle. sizeof (AppleEvent) is 8. So you put the 8 bytes (the type),
and the value of the address of the block's master pointer into your
AEToSend as the '----' parameter. I strongly suspect that's not what you
want to do.
What MAY work is this:
1. Build your AEToInclude in the usual way.
2. Close your eyes (figuratively), and stuff 'reco' into
AEToInclude.descriptorType ['reco' is also known as typeAErecord, and you
should use that constant, IMHO].
3. Now, you should be able to add your AEToInclude to AEToSend with
AEPutParamDesc ().
4. On the other end, knowing what is coming in, get the parameter using
AEGetParamDesc, and stuff typeAppleEvent ('aevt') into the descriptorType
field of the AEDesc.
The above will probably work today. It's asking for trouble.
Do you *really* want to do this??? Or...can you get by with passing an
AERecord, instead? You can make your own AEList of attributes, if needed.
--
John Baxter Port Ludlow, WA, USA [West shore, Puget Sound]
jwbaxter@pt.olympus.net
+++++++++++++++++++++++++++
>From lai@apple.com (Ed Lai)
Date: 25 Feb 1994 17:27:15 GMT
Organization: Apple
> In article <24FEB94.23325740.0070@VM1.MCGILL.CA>, AIKEN
> <INRA000@MUSICB.MCGILL.CA> wrote:
>
> > For reasons of my own (yes, I am sick and twisted) I am trying to
> > add an Apple Event to another Apple event as a paramater. My code
> > looks something like:
> >
> > **
> > AppleEvent AEToSend,AEToInclude;
> >
> > Error=AEPutParamDesc(&AEToSend,keyDirectObject,&AEToInclude);
> > **
> >
> > the AE Manager just barfs up a -1703 err, "Wrong descriptor type".
> > Is this not something I'm supposed to be contemplating, or am I mis-
> > sing something?
>
The Apple Event Manager checks to make sure you cannot stuff an Apple Event
inside another Apple Event, list or record.
--
/* Disclaimer: All statments and opinions expressed are my own */
/* Edmund K. Lai */
/* Apple Computer, MS303-3A */
/* 20525 Mariani Ave, */
/* Cupertino, CA 95014 */
/* (408)974-6272 */
zW@h9cOi
+++++++++++++++++++++++++++
>From AIKEN <INRA000@MUSICB.MCGILL.CA>
Date: Fri, 25 Feb 1994 23:27:21 GMT
Organization: McGill University
In article <lai-250294092517@mac254.kip.apple.com> lai@apple.com (Ed Lai) writes:
>The Apple Event Manager checks to make sure you cannot stuff an Apple Event
>inside another Apple Event, list or record.
Since this is deliberate, I assume there is a logical reason why
this is so. However, I don't see it. What gives?
Mark Aiken
inra@musicb.mcgill.ca
+++++++++++++++++++++++++++
>From AIKEN <INRA000@MUSICB.MCGILL.CA>
Date: Fri, 25 Feb 1994 23:48:43 GMT
Organization: McGill University
In article <jwbaxter-250294004357@ptpm006.olympus.net> jwbaxter@olympus.net (John W. Baxter) writes:
>In article <24FEB94.23325740.0070@VM1.MCGILL.CA>, AIKEN
><INRA000@MUSICB.MCGILL.CA> wrote:
>
>> For reasons of my own (yes, I am sick and twisted) I am trying to
>> add an Apple Event to another Apple event as a paramater. My code
>> looks something like:
[CHOP -- trying AEPutParamDesc doesn't work.]
>> The funny thing is, if I do a AEPutParamPtr like:
>>
>> Error=AEPutParamPtr(&AEToSend,keyDirectObject,'aevt',
>> &AEToInclude,sizeof(AppleEvent));
>
>Not a good idea.
>>
>> Everything is hunky-dory. However, I'm concerned that this method
>> does not make a true duplicate of AEToInclude, which will definately
>> raise hell down the line. This is confusing, however, because both
>> methods should produce a paramater with the same keyword and descriptor
>> type, no?
>
>No. Look at the AEPutParamPtr again. The third parameter points to an
>AppleEvent. If you go back far enough, that's just an AEDesc. A type, and
>a handle. sizeof (AppleEvent) is 8. So you put the 8 bytes (the type),
>and the value of the address of the block's master pointer into your
>AEToSend as the '----' parameter. I strongly suspect that's not what you
>want to do.
I know.
What confuses me is this: AEPutParamDesc with the above usage
should attempt to add a copy of the supplied Apple Event (type: 'aevt')
as the direct paramater. But as a helpful Apple Person (tm) pointed
out, the AE Manager specifically watches out for this. However,
AEPutParamPtr, with the above usage, *also* tries to add a hunk of data
as the direct paramater. The descriptor type, of course, is supplied
in the arguments. AEPutParamPtr is inappropriate here because it doesn't
copy all the associated data of the AE, just its 8-byte descriptor data.
However, I find it confounding that the AE Manager would agree to add
a descriptor record of type 'aevt' from certain calls and not from
others.
>What MAY work is this:
>1. Build your AEToInclude in the usual way.
>2. Close your eyes (figuratively), and stuff 'reco' into
>AEToInclude.descriptorType ['reco' is also known as typeAErecord, and you
>should use that constant, IMHO].
>3. Now, you should be able to add your AEToInclude to AEToSend with
>AEPutParamDesc ().
>4. On the other end, knowing what is coming in, get the parameter using
>AEGetParamDesc, and stuff typeAppleEvent ('aevt') into the descriptorType
>field of the AEDesc.
>
>The above will probably work today. It's asking for trouble.
I'm having trouble understanding why this is all such a bad idea.
An AppleEvent descriptor record just points to a list of other stuff,
namely attributes and parameters, right? So why *shouldn't* I be able
to add it to another AE? Why is the above likely to break in future?
>Do you *really* want to do this??? Or...can you get by with passing an
>AERecord, instead? You can make your own AEList of attributes, if needed.
I don't *really* have to do this. It's just that at one point, I
have data in one AE that another app will need in an AE *it* will send
in response to an AE I'm about to send it (read that slowly!). It
seemed natural to stuff a copy of the pre-fab AE that the other app
will need into the AE I'm about to send it, so that at the other end,
the app can remove the enclosed AE, twiddle the address and maybe one
or two other things, and send it off. No fuss, no muss. Oh, well.
Since both apps know exactly what's supposed to be in the AEs, I
can just bundle all the data into *one* AE, that the receiving app can
rip apart to put together its own AE. But it would have been nice
to be able to send it one already ready to go.
I hadn't thought of your solution, though (thanks!), but I would
love an explanation as to why it's such a bad idea before I start using
it! :-)
Mark Aiken
inra@musicb.mcgill.ca
+++++++++++++++++++++++++++
>From jwbaxter@olympus.net (John W. Baxter)
Date: Sat, 26 Feb 1994 00:13:49 -0800
Organization: Internet for the Olympic Peninsula
In article <25FEB94.20317060.0081@VM1.MCGILL.CA>, AIKEN
<INRA000@MUSICB.MCGILL.CA> wrote:
[a few words of quotation left out]
> I hadn't thought of your solution, though (thanks!), but I would
> love an explanation as to why it's such a bad idea before I start using
> it! :-)
Apple specifies that once you have done your inserting of something into
any of the AE structures, the layout of the contents of the structure are
unknown to you. They do that in part because, I suspect, they are darn
tired of working around the clever things developers have done with
knowledge of such things (like forcing a whole bunch of extra structures in
a color window).
So, in principal, all you know is that you toss some bytes in one end, and
the same byte values come out the other end.
Having said that: You say:
> An AppleEvent descriptor record just points to a list of other stuff,
> namely attributes and parameters, right?
No...it only looks that way. At each stage, the structure is flattened,
and there's only one handle involved with the AEDesc, which contains copies
of everything that has been stuffed in, whether by xxxPtr, or xxxDesc. At
least...it's that way this week (see above).
--
John Baxter Port Ludlow, WA, USA [West shore, Puget Sound]
jwbaxter@pt.olympus.net
+++++++++++++++++++++++++++
>From peter@ncrpda.curtin.edu.au (Peter N Lewis)
Date: 27 Feb 1994 12:52:03 +0800
Organization: NCRPDA, Curtin University
lai@apple.com (Ed Lai) writes:
>The Apple Event Manager checks to make sure you cannot stuff an Apple Event
>inside another Apple Event, list or record.
Stupid question: Why?
Peter.
--
Peter N Lewis <peter.lewis@info.curtin.edu.au> Ph: +61 9 368 2055
+++++++++++++++++++++++++++
>From Patrick C. Beard <beard@cs.ucdavis.edu>
Date: Mon, 28 Feb 1994 01:38:35 GMT
Organization: Dept. Of Computer Science, U.C. Davis
In article <24FEB94.23325740.0070@VM1.MCGILL.CA> AIKEN,
INRA000@MUSICB.MCGILL.CA writes:
> For reasons of my own (yes, I am sick and twisted) I am trying to
>add an Apple Event to another Apple event as a paramater. My code
>looks something like:
>
>**
>AppleEvent AEToSend,AEToInclude;
>
> Error=AEPutParamDesc(&AEToSend,keyDirectObject,&AEToInclude);
>**
>
> the AE Manager just barfs up a -1703 err, "Wrong descriptor type".
>Is this not something I'm supposed to be contemplating, or am I mis-
>sing something?
I ran into the same problem. My solution? Lie to the AppleEvent manager.
There's no reason it has to know the type of a parameter. Just make up
one of your own.
Since an AppleEvent is just an AEDesc with a descriptorType and a
dataHandle,
and the type is always 'aevt', just do the following:
OSErr StuffAE(AppleEvent* event, AppleEvent* nestedEvent)
{
OSErr result;
Handle eventData = nestedEvent->dataHandle;
HLock(eventData);
result = AEPutParamPtr(&event, keyDirectObject, 'stuff', *eventData,
GetHandleSize(eventData));
HUnlock(eventData);
return result;
}
I've used this approach, and it works.
//
// Patrick C. Beard
// Dept. of Computer Science, U. C. Davis
// beard@cs.ucdavis.edu
//
+++++++++++++++++++++++++++
>From lai@apple.com (Ed Lai)
Date: 5 Mar 1994 00:36:19 GMT
Organization: Apple
In article <25FEB94.19932459.0081@VM1.MCGILL.CA>, AIKEN
<INRA000@MUSICB.MCGILL.CA> wrote:
> In article <lai-250294092517@mac254.kip.apple.com> lai@apple.com (Ed Lai) writes:
> >The Apple Event Manager checks to make sure you cannot stuff an Apple Event
> >inside another Apple Event, list or record.
>
> Since this is deliberate, I assume there is a logical reason why
> this is so. However, I don't see it. What gives?
>
> Mark Aiken
> inra@musicb.mcgill.ca
Well, the answer is that the Apple Event Manager is just one of the
implementations of Apple Event, and the Apple Event Transport Format
(it is in one of the tech note) specifies that there can be no
Apple Event embedded in another Apple Event.
Then the question is why the AETF specifies this. I guess it is
partly not to make it too complicated, and partly because an
embedded Apple Event can be misleading. Let say you create Apple
Event A and B in a machine X with some valid session id as the target
address, you embed B into A and send it off to another machine.
When it arrives at the other machine Y, the adress of Apple Event
A will be valid on arrival. However, if you pull out the Apple
Event B from Apple Event A, you get an Apple Event with an
session ID from machine X which is invalid in machine Y.
--
/* Disclaimer: All statments and opinions expressed are my own */
/* Edmund K. Lai */
/* Apple Computer, MS303-3A */
/* 20525 Mariani Ave, */
/* Cupertino, CA 95014 */
/* (408)974-6272 */
zW@h9cOi
---------------------------
>From dresden@albert.ma.utexas.edu (Greg Dresden)
Subject: Why use handles at all, though?
Date: 1 Mar 1994 16:43:35 -0600
Organization: University Of Texas Mathematics
Concerning the current debate about handles:
I've been reading with great interest these articles about when to lock 'em,
when to unlock 'em, and when to walk away.
>From what I can pick up, it seems as if these handles are simply
pointers to pointers. (Alas, I must have been asleep when we discussed these
in class.)
If this is so, why would anyone want to: (a) use handles when you could
just use pointers, and (b) use a "with" statement when you could just
type out the pointer's full name (thus saving yourself much grief.)
Now, I am a still-wet-behind-the-ears newbie, but I can't really
see the value of handles as a programming tool.
Are there any enlightened gurus out there who would like to rush to the
defense of these much-maligned objects?
- --------------------------------------------------
dresden@albert.ma.utexas.edu
+++++++++++++++++++++++++++
>From mssmith@afterlife.ncsc.mil (M. Scott Smith)
Date: Wed, 2 Mar 1994 13:10:43 GMT
Organization: The Great Beyond
In article <2l0gen$k3e@albert.ma.utexas.edu> dresden@albert.ma.utexas.edu (Greg Dresden) writes:
>Concerning the current debate about handles:
>
>I've been reading with great interest these articles about when to lock 'em,
>when to unlock 'em, and when to walk away.
>
>From what I can pick up, it seems as if these handles are simply
>pointers to pointers. (Alas, I must have been asleep when we discussed these
>in class.)
>
>If this is so, why would anyone want to: (a) use handles when you could
>just use pointers [...]
I'll try to tackle this one..
Memory management on the Macintosh is different than most other
computers. When the Mac first came out, it didn't have much memory
available for applications' use. And Mac programs -- being graphical,
etc., tended to take up more memory than their text counterparts (even
though a lot of the Toolbox calls were in ROM.)
Because of this, it was necessary to create a very efficient memory
model.
Let's first look at the traditional way of allocating memory with
pointers.
When you first run a program, a chunk of memory is set aside. Then,
whenever you call NewPtr, you're taking away from that chunk.
Say the memory partition is 200 kilobytes. You go along and allocate
100k with a pointer. Now memory looks like this:
- --
|XX| 100k (allocated)
|XX|
|--|
| | 100k (available)
| |
- --
Now you allocate 30k. After that, you deallocate the 100k. Now
memory looks like this:
- --
| | 100k (available)
| |
|XX| 30k (allocated)
| |
| | 70k (available)
- --
Now say you need to allocate 110k.
You can't. You can allocate up to 100k, but no more, even though you've
technically got 170k available.
Why? Because you've fragmented the heap, as they say. I've really
simplified things here; you can imagine just how fragmented the heap can
get before too long, especially if it's not all that large to begin with
(the ideal).
Wouldn't it be great if the computer was smart enough to, say, move
that 30k down to the bottom of the heap so you could allocate the whole
170k?
Enter handles. As if pointers weren't confusing enough, now you've
got pointers to pointers (to pointers to pointers to..) Say we wanted
to solve our problem using pointers; we wanted to make the computer
intelligent enough to rearrange memory. The problem is, we've got a
local variable which is a pointer to a memory address that locates your
allocation on the heap. If the memory manager moved your allocation
on the heap, your pointer would still be pointing at the old address --
which is most likely NOT what you want. (Unless you're one of those
"grunge" programmers.)
With handles, you still maintain a pointer, but it points to a pointer
which is maintained by the memory manager, and not you. That way, the
memory manager is free to do anything it wants with memory -- so long
as it updates that pointer it's maintaining to reflect the new location
of your memory.
So long as you use YOUR pointer, you will be safe; it will always be
pointing to a pointer which points to the correct address of your memory,
even if that address changes.
Other issues come up, though. Dereferencing a pointer twice is a lot
slower than dereferencing a pointer once, so you'll probably want to
dereference that handle to get to the pointer that points straight to
the data, when you want to access that data.
This can be dangerous, because the memory manager can change it at
any time (and your dereference won't reflect that change!) When can the
memory manager move things around in the heap? Just about anytime it
feels like it. Many (most?) of the Toolbox functions can trigger memory
manager activity. If you do dereference a handle, you should be careful
that memory isn't going to move; if you're uncertain, you can "lock"
the handle down, which guarantees the memory manager won't move it.
(You should unlock it when you're done so it can move it. After all,
that's the whole point.)
Does that help clear things up a bit?
Scott
- -
M. Scott Smith
Macintosh developer, student, ski bum. Eater of Cadbury's Creme Eggs.
+++++++++++++++++++++++++++
>From gurgle@netcom.com (Pete Gontier)
Date: Wed, 2 Mar 1994 19:51:32 GMT
Organization: cellular
dresden@albert.ma.utexas.edu (Greg Dresden) writes:
>I've been reading with great interest these articles about when to
>lock 'em, when to unlock 'em, and when to walk away. From what I can
>pick up, it seems as if these handles are simply pointers to pointers.
>(Alas, I must have been asleep when we discussed these in class.) If
>this is so, why would anyone want to: (a) use handles when you could
>just use pointers...
What's misleading about many articles which discuss the pitfalls of
handle-based memory management is that they focus on the pitfalls, not
surprisingly. In fact, there is so much discussion of the pitfalls that
it must seem like handles are just a bogus design waiting to cause bugs
in otherwise innocent programs. However, handles have real positive
effects when used in low-memory siuations, because they can be moved and
recombined and shuffled in general within a heap to make the maximum
possible blocks size available to whoever needs it.
> ...and (b) use a "with" statement when you could just type out the
>pointer's full name (thus saving yourself much grief.)
Most people use WITH statements just for convenience. In some cases,
that convenience can be non-trivial. Suppose you have several nested
records. You know that a certain piece of code wants to access the
fields of one of the most deeply nested records. Suppose further that
you would like to be able to reorganize the containment structure of
this deeply nested record if and when necessary. The WITH statement,
used properly, would theoretically allow you to change less code,
thereby reducing the chance of introducing a typographical error which
coincidentally compiles without error.
In most cases, though, I think you're right: WITH is just expedient.
>Are there any enlightened gurus out there who would like to rush to the
>defense of these much-maligned objects?
IMO (and there are plenty who disagree with me), the era of handles is
largely over. People used to allocate handles whenever they needed a
hunk of memory out of the heap. This was necessary because the Mac had
very little memory. Now that customers expect applications to be huge,
I think you can get away with allocating pointers a lot of the time.
Large chunks of memory should probably still be in pointers. Also, don't
conclude that I think applications can be and should be huge these days.
That's obviously an unsupportable position. I am merely pointing out
that since many apps are huge, there's a little more weight on the side
of the scale for safety and robustness (pointers) than there used to be.
Also, don't use NewPtr or malloc. But that's another story altogether.
--
Pete Gontier, CTO, Integer Poet Software; gurgle@netcom.com
+++++++++++++++++++++++++++
>From u9119523@sys.uea.ac.uk (Graham Cox)
Date: Thu, 3 Mar 1994 15:43:15 GMT
Organization: School of Information Systems, UEA, Norwich
In article <gurgleCM1z5y.4J1@netcom.com>, gurgle@netcom.com (Pete Gontier)
wrote:
> dresden@albert.ma.utexas.edu (Greg Dresden) writes:
>
[SNIP!]
Just to add my two-penn'orth...
Once you understand WHY handles exist and HOW to use them, you hardly ever
use pointers again, and your ability as a programmer of truly stable, solid
Mac programs takes a massive leap forward. That was my experience anyway
(was it really 1986...?)
- ------------------------------------------------------------------------
Love & BSWK, Graham
-Everyone is entitled to their opinion, no matter how wrong they may be...
- ------------------------------------------------------------------------
+++++++++++++++++++++++++++
>From gurgle@netcom.com (Pete Gontier)
Date: Thu, 3 Mar 1994 20:52:39 GMT
Organization: cellular
gurgle@netcom.com (Pete Gontier) writes:
>Large chunks of memory should probably still be in pointers.
Yow! Here I was trying to be responsible and I let a zinger like THIS go
by. It should have read:
>Large chunks of memory should probably still be in handles.
--
Pete Gontier, CTO, Integer Poet Software; gurgle@netcom.com
+++++++++++++++++++++++++++
>From rang@winternet.mpls.mn.us (Anton Rang)
Date: 04 Mar 1994 00:35:07 GMT
Organization: Minnesota Angsters
In article <gurgleCM1z5y.4J1@netcom.com> gurgle@netcom.com (Pete Gontier) writes:
>However, handles have real positive
>effects when used in low-memory siuations, because they can be moved and
>recombined and shuffled in general within a heap to make the maximum
>possible blocks size available to whoever needs it.
Not just in low-memory situations, either; any time that you need to
have a memory block whose size varies dynamically, a handle is *very*
useful....
--
Anton Rang (rang@acm.org)
+++++++++++++++++++++++++++
>From Brad Koehn <koehn@macc.wisc.edu>
Date: 4 Mar 1994 01:30:22 GMT
Organization: University of Wisconsin
In article <gurgleCM1z5y.4J1@netcom.com> Pete Gontier, gurgle@netcom.com
writes:
>IMO (and there are plenty who disagree with me), the era of handles is
>largely over.
I guess I'm one of those people.
>People used to allocate handles whenever they needed a
>hunk of memory out of the heap. This was necessary because the Mac had
>very little memory.
That's still true. You can never have enough memory, and one pointer can
cut the RAM you have in half, no matter how much you have.
I'm kind of a purist, I love the Mac memory model (well, not all of it,
but within a heap anyway) and thinks it's just great. I can make great
programs that require hardly any memory to run, and they have all kinds
of cool memory management w/o requiring an MMU.
As long as I assume that my handles are going to move all the time,
everything's kosher. Wait, that's not true. My handles don't move all the
time, they only do during most trap calls. I don't bother to check which
ones (unless I'm in speed critical code), I just lock and unlock as
necessary. As it turns out, it's usually not all that necessary. And on
top of that, I get a nice clean heap.
I do wish that HLock and HUnlock weren't traps though, it bothers me that
my precious clock cycles are being stolen by the trap dispatcher (esp.
with TCL...).
_________________________________________________________________________
Brad Koehn Data Transformations, Inc. koehn@macc.wisc.edu
+++++++++++++++++++++++++++
>From ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University)
Date: 4 Mar 94 17:02:44 +1300
Organization: University of Waikato, Hamilton, New Zealand
In article <2l0gen$k3e@albert.ma.utexas.edu>, dresden@albert.ma.utexas.edu (Greg Dresden) writes:
> Concerning the current debate about handles:
>
> I've been reading with great interest these articles about when to lock 'em,
> when to unlock 'em, and when to walk away.
>
> From what I can pick up, it seems as if these handles are simply
> pointers to pointers. (Alas, I must have been asleep when we discussed these
> in class.)
Ar, that be right.
> If this is so, why would anyone want to: (a) use handles when you could
> just use pointers,...
The thing about handles is that the memory blocks can move about in memory.
This has two consequences:
1) Fragmentation is less likely when memory is running low, and
2) You can resize the blocks.
Reason 1 is less important when you have megabytes to play with. However, 2
is still a very useful property: it's handy for creating all kinds of
dynamically-sized structures--arrays and the like.
> and (b) use a "with" statement when you could just
> type out the pointer's full name (thus saving yourself much grief.)
Beats me, too...
> Now, I am a still-wet-behind-the-ears newbie, but I can't really
> see the value of handles as a programming tool.
I trust I have managed to disabuse you of that notion.
Lawrence
a member of the society for linking things to other things.
+++++++++++++++++++++++++++
>From D.A.G.Gillies@bradford.ac.uk (DAG GILLIES)
Date: Fri, 4 Mar 1994 12:40:41 GMT
Organization: University of Bradford, UK
In article <gurgleCM1z5y.4J1@netcom.com> gurgle@netcom.com (Pete Gontier) writes:
>dresden@albert.ma.utexas.edu (Greg Dresden) writes:
>
>>Are there any enlightened gurus out there who would like to rush to the
>>defense of these much-maligned objects?
>
>IMO (and there are plenty who disagree with me), the era of handles is
>largely over. People used to allocate handles whenever they needed a
>hunk of memory out of the heap. This was necessary because the Mac had
>very little memory. Now that customers expect applications to be huge,
>I think you can get away with allocating pointers a lot of the time.
>Large chunks of memory should probably still be in pointers. Also, don't
>conclude that I think applications can be and should be huge these days.
>That's obviously an unsupportable position. I am merely pointing out
>that since many apps are huge, there's a little more weight on the side
>of the scale for safety and robustness (pointers) than there used to be.
>Also, don't use NewPtr or malloc. But that's another story altogether.
>--
I like handles from an aesthetic point of view - they seem to me to be
a nice way of handling dynamic memory. I have a general rule of thumb for
when to use handles and when to use pointers, and it relies mainly on the
scope and lifetime of the entity for which storage is being allocated. In
general, if I am allocating an object at global scope, I will use a handle,
to allow that object to waft around the heap and maximise available memory.
Typically, where it is being used in a function, I will lock it down (and
high) with HLockHi for the duration of that function and than free it up
again at the end. This allows me to dereference it once at the beginning of
the function for speed. However, if I am allocating an object that only
exists at local scope, and which will be destroyed when the enclosing
function returns, I will use a pointer, unless the object is needed by a
lot of functions called by the enclosing function, in which case I may well
use a Handle (and possibly lock it down as before).
If I am messing with resource creation (like building Finder aliases), I
will use Handles, simply because resources are Handles themselves, and
in general speed is not critical in such cases.
______________________________________________________
David A. G. Gillies (D.A.G.Gillies@bradford.ac.uk)
(c) 1994 Wittgenstein's Amazing Underwater Supermarket
- -------------REPLIES VIA EMAIL PLEASE---------------
_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
+++++++++++++++++++++++++++
>From partingt@fwi.uva.nl (Vincent Partington)
Date: 4 Mar 1994 16:08:49 GMT
Organization: FWI, University of Amsterdam
gurgle@netcom.com (Pete Gontier) writes:
>>Large chunks of memory should probably still be in pointers.
>Yow! Here I was trying to be responsible and I let a zinger like THIS go
>by. It should have read:
>>Large chunks of memory should probably still be in handles.
It doesn't really matter if you put large or small objects in handles.
Small objects break up the heap just as good as big objects. So if you go
with handles, go with them all the way.
Vincent.
BTW, Why isn't there a TempNewPtr call? To prevent us from cluttering the
temporary heap?
--
VI is better than Emacs. | Let's | Internet : partingt@fwi.uva.nl
MacOS is better than Windows. | start the | vincent@tnc.nl
Unix is better than VMS. | religious | FidoNet : 2:281/202.15
Eiffel is better than C++. | war!! | NeST : 90:500/202.15
+++++++++++++++++++++++++++
>From gurgle@netcom.com (Pete Gontier)
Date: Fri, 4 Mar 1994 20:09:41 GMT
Organization: cellular
rang@winternet.mpls.mn.us (Anton Rang) writes:
>In article <gurgleCM1z5y.4J1@netcom.com> gurgle@netcom.com (Pete Gontier) writes:
>>However, handles have real positive
>>effects when used in low-memory siuations, because they can be moved and
>>recombined and shuffled in general within a heap to make the maximum
>>possible blocks size available to whoever needs it.
>Not just in low-memory situations, either; any time that you need to
>have a memory block whose size varies dynamically, a handle is *very*
>useful....
That depends on how you define "useful", of course.
If you are, for example, talking about adding a couple of bytes to
a handle which takes up more than half the heap, which would be
impossible without handles, I would call that part of the low-memory
considerations.
The other aspects of it are about convenience and performance, not space
savings. And it's true that these also are reasons to advocate handles.
But if you can't do something at all, it doesn't matter how convenient
or fast it would have been. :-)
--
Pete Gontier, CTO, Integer Poet Software; gurgle@netcom.com
+++++++++++++++++++++++++++
>From gurgle@netcom.com (Pete Gontier)
Date: Fri, 4 Mar 1994 20:18:09 GMT
Organization: cellular
Brad Koehn <koehn@macc.wisc.edu> writes:
> ...one pointer can cut the RAM you have in half, no matter how much
> you have.
Sure, that's true. But I'd say it's easier for the most part to keep
this in mind and avoid it rather than use handles all the time. I'm not
suggesting people allocate pointers for long-term global-state storage.
If, well into a program's lifetime, it decides it's going to allocate
a text buffer and leave it hanging around indefinitely, that buffer
shouldn't go into a pointer. For all it knows, a properly written
function has been called deep in a call hierarchy, and several bazillion
pointers may already have been allocated on the heap. Allocating another
and leaving it around could easily frag the heap and reduce the amount
of memory available to any one block.
>My handles don't move all the time, they only do during most trap
>calls. I don't bother to check which ones (unless I'm in speed critical
>code), I just lock and unlock as necessary.
I usually assume StripAddress and BlockMove are not going to move
memory, but that's about it. :-)
BTW, also remember to be paranoid about inter-segment calls.
--
Pete Gontier, CTO, Integer Poet Software; gurgle@netcom.com
+++++++++++++++++++++++++++
>From mxmora@unix.sri.com (Matt Mora)
Date: 4 Mar 1994 09:27:52 -0800
Organization: SRI International, Menlo Park, CA
In article <2l62ve$97p@news.doit.wisc.edu> Brad Koehn <koehn@macc.wisc.edu> writes:
>In article <gurgleCM1z5y.4J1@netcom.com> Pete Gontier, gurgle@netcom.com
>writes:
>>IMO (and there are plenty who disagree with me), the era of handles is
>>largely over.
>
>I guess I'm one of those people.
Me too. (if your talking about wanting to keep Handles) I think Handles
are cool but always wished they did more. Why couldn't handles, when being
moved to make room, jump over locked blocks? Handles can become pretty useless
if there are a few locked blocks in memory. I think handles should have been
more automagic. The memeory manager should take care of the details for me.
For example. Why couldn't we call one function to tell the memory
manager that we are about to use the data thats in the handle. ie:
HUsingHandle(h);
<do what ever I want with the handle because its is now in a safe state>
HNotUsingHandle(h);
After marking the handle as not in use, the system is now free to do anything
it wants with the handle. That includes paging it to disk, moving it around,
jumping over locked memory islands, or even compressing it.
Certain functions would call these functions internally like DrawPicture.
So you know that when you call drawpicture the system would do anything
that it needs to bring the handle to a safe state and then use the data.
With the PowerPC machines, things like this are possible.
Xavier
--
___________________________________________________________
Matthew Xavier Mora Matt_Mora@qm.sri.com
SRI International mxmora@unix.sri.com
333 Ravenswood Ave Menlo Park, CA. 94025
+++++++++++++++++++++++++++
>From j-norstad@nwu.edu (John Norstad)
Date: Fri, 04 Mar 1994 18:41:08 -0600
Organization: Northwestern University
In article <2l0gen$k3e@albert.ma.utexas.edu>, dresden@albert.ma.utexas.edu
(Greg Dresden) wrote:
> Are there any enlightened gurus out there who would like to rush to the
> defense of these much-maligned objects?
Yes, I will.
Relocatable memory blocks are incredibly useful for storying varying
amounts of data when you don't know in advance how much memory you are
going to need, and when the memory needs grow and shrink during the
lifetime of the block.
The Mac memory manager can easily make a relocatable block larger by
moving it or by moving other relocatable blocks out of the way. This is
not possible in fixed block systems.
This is incredibly useful. All of my Mac programs make extensive use of
this feature of the Mac memory manager, and would be very significantly
more difficult to write on a system without relocatable blocks.
For example, in my NewsWatcher program, I use this in dozens of places.
It's an extraordinarily useful technique. I have grow so accustomed to
having it that I find it difficult to live without it when I have to deal
with programming on other systems. Programing without relocatable and
growable blocks is like returning to the pre-Mac stone ages for me.
SetHandleSize(h, GetHandleSize(h) + n) is one of my favorite lines of C on
the Mac, and is one of the many reasons I find programming the Mac to be
much more fun and pleasant than programming other kinds of computers.
Yes, you do have to be very careful about dangling pointers. It's the
price paid for the flexibility.
I have also used a system (Control Data's NOS/VE) where each process could
use a very large number of very large separate virtual address spaces. On
those systems, you put varying size objects in their own address space.
--
John Norstad
Academic Computing and Network Services
Northwestern University
j-norstad@nwu.edu
+++++++++++++++++++++++++++
>From ari@world.std.com (Ari I Halberstadt)
Date: Sat, 5 Mar 1994 11:18:56 GMT
Organization: The World Public Access UNIX, Brookline, MA
In article <2l7r2o$t2f@unix.sri.com>, Matt Mora <mxmora@unix.sri.com> wrote:
>Me too. (if your talking about wanting to keep Handles) I think Handles
>are cool but always wished they did more. Why couldn't handles, when being
If we're on the subject of wish lists...
How about a language with a decent garbage collection coroutine? Since
the garbage collector would track all memory references, we could let
the garbage collector automagically compact the heap for us. Handles
would be obsolete and most memory errors would be obsolete (e.g.,
using disposed memory, forgetting to dispose of memory, even address
and bus errors would be very rare with such a language). To top it all
off, our programs would be a heck of a lot simpler and easier to write
and maintain. I wouldn't worry too much about speed. Algorithms are
always getting better, and we can always just throw another CPU at the
problem (i.e., parallelize the garbage collection).
--
Ari Halberstadt ari@world.std.com #include <std/disclaimer.h>
"These beetles were long considered to be very rare because very few
entomologists look for beetles in the mountains, in winter, at night,
during snow storms." -- Purves W. K., et al, "Life: The Science of
+++++++++++++++++++++++++++
>From gurgle@netcom.com (Pete Gontier)
Date: Sat, 5 Mar 1994 22:28:41 GMT
Organization: cellular
partingt@fwi.uva.nl (Vincent Partington) writes:
>gurgle@netcom.com (Pete Gontier) writes:
>>>Large chunks of memory should probably still be in pointers.
>>Yow! Here I was trying to be responsible and I let a zinger like THIS go
>>by. It should have read:
>>>Large chunks of memory should probably still be in handles.
>It doesn't really matter if you put large or small objects in handles.
>Small objects break up the heap just as good as big objects. So if you go
>with handles, go with them all the way.
I don't think this is valid. If you know what you are doing, it does
in fact make sense to put small objects in pointers and large objects
in handles in many contexts. Size is not the only consideration, as I
posted elsewhere; however, large objects should probably go in handles
regardless of other considerations; I believe that would have been more
evident if I had quoted more of the original message.
--
Pete Gontier, CTO, Integer Poet Software; gurgle@netcom.com
+++++++++++++++++++++++++++
>From ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University)
Date: 7 Mar 94 14:57:51 +1300
Organization: University of Waikato, Hamilton, New Zealand
In article <u9119523-030394154315@case6.sys.uea.ac.uk>, u9119523@sys.uea.ac.uk (Graham Cox) writes:
>
> Once you understand WHY handles exist and HOW to use them, you hardly ever
> use pointers again, and your ability as a programmer of truly stable, solid
> Mac programs takes a massive leap forward. That was my experience anyway
> (was it really 1986...?)
My Mac experience dates from about the same time (I started getting seriously
into Mac programming about 86/87), and I would say "No way!".
I wrote some code which created a sorted tree structure once. Initially each
block was relocatable. Every now and then, the program would print garbage for
the contents of a tree node. Obviously a block was moving unexpectedly from
under me.
Rather than try to track down the exact place where I was forgetting to lock
the block, I changed all the relocatable blocks for the tree nodes to
nonrelocatable ones. This is how a conventional tree or linked list structure
is built in the textbooks, anyway. The program worked fine after that.
Moral: use nonrelocatable blocks for large numbers of identically-sized blocks.
I don't think that creating large numbers of handles is a good idea (unless
you manage the master pointers quite carefully). If you're doing a lot of
allocating and deallocating of blocks of a particular size, you could create
a lookaside list to speed things up. I tend to use handles where the system
encourages (or forces) me to, and where I need resizable structures.
And, yes, I do make frequent use of resizable structures.
Lawrence D'Oliveiro fone: +64-7-856-2889
Info & Tech Services Division fax: +64-7-838-4066
University of Waikato electric mail: ldo@waikato.ac.nz
Hamilton, New Zealand 37^ 47' 26" S, 175^ 19' 7" E, GMT+13:00
+++++++++++++++++++++++++++
>From bcollett@hamilton.edu (Brian Collett)
Date: 8 Mar 1994 17:13:07 GMT
Organization: Hamilton College
In article <1994Mar7.145751.26071@waikato.ac.nz>, ldo@waikato.ac.nz
(Lawrence D'Oliveiro, Waikato University) wrote:
> Moral: use nonrelocatable blocks for large numbers of identically-sized blocks.
> I don't think that creating large numbers of handles is a good idea (unless
> you manage the master pointers quite carefully). If you're doing a lot of
> allocating and deallocating of blocks of a particular size, you could create
> a lookaside list to speed things up. I tend to use handles where the system
> encourages (or forces) me to, and where I need resizable structures.
If you are manipulating large numbers of identical blocks then it is highly
advantageous to pre-allocate a large chunk of them and then manage them
yourself (I use a simple linked list of free blocks). Identical size blocks
have no fragmentation problems and you can write a MUCH faster memory
manager for them. I have cut the memory manager overhead in a program that
manipulates many dynamic blocks from >50% of the total execution time to
<10% by this trick.
Brian Collett, Physics Dept., Hamilton College, Clinton, NY 13323
+++++++++++++++++++++++++++
>From Brad Miller <miller@cs.rochester.edu>
Date: Tue, 8 Mar 1994 17:16:27 -0500
Organization: University of Rochester Computer Science Dept
>>>>> "Ari" == Ari I Halberstadt <ari@world.std.com> writes:
Ari> In article <2l7r2o$t2f@unix.sri.com>, Matt Mora <mxmora@unix.sri.com> wrote:
>> Me too. (if your talking about wanting to keep Handles) I think Handles are cool but always wished they did
>> more. Why couldn't handles, when being
Ari> If we're on the subject of wish lists...
Ari> How about a language with a decent garbage collection coroutine? Since the garbage collector would track all
Ari> memory references, we could let the garbage collector automagically compact the heap for us. Handles would be
Ari> obsolete and most memory errors would be obsolete (e.g., using disposed memory, forgetting to dispose of
Ari> memory, even address and bus errors would be very rare with such a language). To top it all off, our programs
Ari> would be a heck of a lot simpler and easier to write and maintain. I wouldn't worry too much about
Ari> speed. Algorithms are always getting better, and we can always just throw another CPU at the problem (i.e.,
Ari> parallelize the garbage collection). -- Ari Halberstadt ari@world.std.com #include <std/disclaimer.h> "These
Ari> beetles were long considered to be very rare because very few entomologists look for beetles in the mountains,
Ari> in winter, at night, during snow storms." -- Purves W. K., et al, "Life: The Science of
It already exists, it's called "Lisp". The apple implementation, "Macintosh
Common Lisp" is quite good too.
Handles shouldn't be needed with any "real" VM. Arguably, the same is true for garbage, if you have a big enough heap.
+++++++++++++++++++++++++++
>From tblanch@lookout.ecte.uswc.uswest.com (Todd Blanchard)
Date: Mon, 7 Mar 1994 23:44:48 GMT
Organization: US WEST Information Technologies
Graham Cox (u9119523@sys.uea.ac.uk) wrote:
: In article <gurgleCM1z5y.4J1@netcom.com>, gurgle@netcom.com (Pete Gontier)
: wrote:
: > dresden@albert.ma.utexas.edu (Greg Dresden) writes:
: >
: [SNIP!]
: Just to add my two-penn'orth...
: Once you understand WHY handles exist and HOW to use them, you hardly ever
: use pointers again, and your ability as a programmer of truly stable, solid
: Mac programs takes a massive leap forward. That was my experience anyway
: (was it really 1986...?)
Perhaps, but I'm rather used to doing things like:
myObject = new Object();
myObject->Message();
delete myObject;
This is the very stuff of C++ and I really like it. Handles are OK for
buffers and such but they don't make C++ very nice to implement. A good
VM system sort of negates the value of the things.
JMO
Todd Blanchard
+++++++++++++++++++++++++++
>From peirce@outpost.SF-Bay.org (Michael Peirce)
Date: Fri, 11 Mar 94 11:23:45 PST
Organization: Peirce Software, Inc.
In article <j-norstad-040394184108@aragorn12.acns.nwu.edu> (comp.sys.mac.programmer), j-norstad@nwu.edu (John Norstad) writes:
> In article <2l0gen$k3e@albert.ma.utexas.edu>, dresden@albert.ma.utexas.edu
> (Greg Dresden) wrote:
>
> > Are there any enlightened gurus out there who would like to rush to the
> > defense of these much-maligned objects?
>
> Yes, I will.
>
> Relocatable memory blocks are incredibly useful for storying varying
> amounts of data when you don't know in advance how much memory you are
> going to need, and when the memory needs grow and shrink during the
> lifetime of the block.
>
> The Mac memory manager can easily make a relocatable block larger by
> moving it or by moving other relocatable blocks out of the way. This is
> not possible in fixed block systems.
>
> This is incredibly useful. All of my Mac programs make extensive use of
> this feature of the Mac memory manager, and would be very significantly
> more difficult to write on a system without relocatable blocks.
I agree with John. Handles are really useful mainly because they
are resizable. You simply can't do this with simple pointers.
I don't really understand why some people want to banish handles and
regress to a pointer only memory model. Yuck.
-- Michael Peirce -- peirce@outpost.sf-bay.org
-- Peirce Software, Inc. -- 719 Hibiscus Place, Suite 301
-- -- San Jose, California USA 95117
-- Makers of: Smoothie & -- voice: +1.408.244.6554 fax: +1.408.244.6882
-- Peirce Print Tools -- AppleLink: peirce & America Online: AFC Peirce
+++++++++++++++++++++++++++
>From platypus@cirrus.som.cwru.edu (Gary Kacmarcik)
Date: 11 Mar 1994 23:13:44 GMT
Organization: Case Western Reserve University, Cleveland, Ohio (USA)
In article <CNjbKKKX.qc1a0h@outpost.SF-Bay.org> peirce@outpost.SF-Bay.org (Michael Peirce) writes:
>
> In article <j-norstad-040394184108@aragorn12.acns.nwu.edu> (comp.sys.mac.programmer), j-norstad@nwu.edu (John Norstad) writes:
> >
> > Relocatable memory blocks are incredibly useful for storying varying
> > amounts of data when you don't know in advance how much memory you are
> > going to need, and when the memory needs grow and shrink during the
> > lifetime of the block.
> >
> > The Mac memory manager can easily make a relocatable block larger by
> > moving it or by moving other relocatable blocks out of the way. This is
> > not possible in fixed block systems.
>
> I agree with John. Handles are really useful mainly because they
> are resizable. You simply can't do this with simple pointers.
while i agree that handles are useful. pointers _can_ be resizable.
for example, the following routine:
int ReallocPtr(Ptr *p,Size newSize) {
Ptr new_p;
// try to resize the pointer
SetPtrSize(p,newSize);
if(MemError() == noErr)
return(0);
// couldn't simply resize, re-allocate the ptr
new_p = NewPtrClear(newSize);
if(MemError() != noErr)
return(1);
// copy the data from the old area to the new area
BlockMove(*p,new_p,GetPtrSize(*p));
// trash the old ptr
DisposePtr(*p);
*p = new_p;
return(0);
}
this does basically the same thing that ResizeHandle() does with handles
or that realloc() does for pointers in ANSI C.
anyway, handles are more convenient than using the above code, but
i just wanted to show that Ptr's _can_ be resized.
-gary j kacmarcik
platypus@curie.ces.cwru.edu
+++++++++++++++++++++++++++
>From u9119523@sys.uea.ac.uk (Graham Cox)
Date: Fri, 11 Mar 1994 12:37:54 GMT
Organization: School of Information Systems, UEA, Norwich
In article <CMBJAo.H8t@da_vinci.it.uswc.uswest.com>,
tblanch@lookout.ecte.uswc.uswest.com (Todd Blanchard) wrote:
> Graham Cox (u9119523@sys.uea.ac.uk) wrote:
> : In article <gurgleCM1z5y.4J1@netcom.com>, gurgle@netcom.com (Pete Gontier)
> : wrote:
>
> : > dresden@albert.ma.utexas.edu (Greg Dresden) writes:
> : >
> : [SNIP!]
>
> : Just to add my two-penn'orth...
>
> : Once you understand WHY handles exist and HOW to use them, you hardly ever
> : use pointers again, and your ability as a programmer of truly stable, solid
> : Mac programs takes a massive leap forward. That was my experience anyway
> : (was it really 1986...?)
>
> Perhaps, but I'm rather used to doing things like:
>
> myObject = new Object();
> myObject->Message();
> delete myObject;
Yeah, me too!
>
> This is the very stuff of C++ and I really like it. Handles are OK for
> buffers and such but they don't make C++ very nice to implement. A good
> VM system sort of negates the value of the things.
>
> JMO
> Todd Blanchard
I don't see why. A handle is a mechanism for implemeinting efficient memory
usage. In the original (non C++) implementation of the THINK class library
objects WERE handles. Did the programmer care? No- the indirection was
hidden from the programmer. Upshot- easy to write syntax PLUS efficient
memory management. In C++ I believe that objects are pointers. What
difference does it make to the programmer?- none. The syntax is identical.
The code is portable. However the fragmentation problem is still there, and
presumably C++ apps either suffer as a result or have their own memory
management code.
Personally, though I'm very much sold on OOP, I still like and appreciate
handles, and would prefer that C++ implemented object as handles.
- ------------------------------------------------------------------------
Love & BSWK, Graham
-Everyone is entitled to their opinion, no matter how wrong they may be...
- ------------------------------------------------------------------------
+++++++++++++++++++++++++++
>From rang@winternet.mpls.mn.us (Anton Rang)
Date: 12 Mar 1994 04:48:12 GMT
Organization: Minnesota Angsters
In article <PLATYPUS.94Mar11181344@cirrus.som.cwru.edu> platypus@cirrus.som.cwru.edu (Gary Kacmarcik) writes:
>while i agree that handles are useful. pointers _can_ be resizable.
> [ ... example of re-allocating pointers, pass in ptr, pass out ptr ... ]
The problem with re-allocating a pointer using such a routine is
that it doesn't update any *other* pointers to the same memory block.
So if you have a data structure whose size needs to change, you need
to track every pointer to it. At that point, you're just re-inventing
handles.
--
Anton Rang (rang@winternet.mpls.mn.us)
+++++++++++++++++++++++++++
>From gurgle@netcom.com (Pete Gontier)
Date: Sat, 12 Mar 1994 06:03:23 GMT
Organization: cellular
platypus@cirrus.som.cwru.edu (Gary Kacmarcik) writes:
>while i agree that handles are useful. pointers _can_ be resizable.
>for example, the following routine:
>int ReallocPtr(Ptr *p,Size newSize) {
> ...
> return(0);
> }
If this is an actual routine you are using, allow me to make a
suggestion. Since it always returns 0, you might care to change it so it
returns the resized pointer.
void * ReallocPtr (void *p, Size newSize);
I am using something like this and it works dandy. What returning the
resized pointer buys you is less nasty casting to get the parameter right.
With the original version, you might have to do something like this:
void foo (int *bar)
{
int x = ReallocPtr ((Ptr *) &bar, sizeof (*bar));
}
I know I would get this cast wrong more often than I care to admit.
With the newer declaration, you could write the same function like this:
void foo (int *bar)
{
bar = ReallocPtr (bar,sizeof (*bar));
}
--
Pete Gontier, CTO, Integer Poet Software; gurgle@netcom.com
+++++++++++++++++++++++++++
>From john_werner@taligent.com (John Werner)
Date: Sat, 12 Mar 1994 07:18:31 GMT
Organization: Taligent, Inc.
In article <u9119523-110394123755@graphics9.sys.uea.ac.uk>,
u9119523@sys.uea.ac.uk (Graham Cox) wrote:
> In the original (non C++) implementation of the THINK class library
> objects WERE handles.
They still are, unfortunately.
> Did the programmer care?
Yes. You have to be very careful to lock TCL objects if you're going to
pass around pointers to any of their fields. References make this even
worse, since it's not clear from looking at a piece of code whether
references are involved.
Code as innocuous looking as this:
class foo : public TObject {
Complex a, b;
Complex bar();
};
Complex foo::bar() { return a + b; }
can screw you up if operator+ uses references and foo::bar is in an
unloaded segment.
It could be argued that this is a compiler bug. The C++ standard (such as
it is) says that references and pointers are supposed to refer or point to
the original object for as long as it exists. In this case they don't.
> Upshot- easy to write syntax PLUS efficient memory management.
It's quite possible to write an efficient pointer-based memory manager.
Heaps may take up a bit more space, but they're a lot faster, since you can
don't have to move blocks around all the time. With decent virtual memory,
large resizable blocks like editing buffers aren't a big issue, because you
can use memory-mapped files (ala Unix's mmap) for them.
--
John Werner john_werner@taligent.com
Taligent, Inc.
+++++++++++++++++++++++++++
>From sw@network-analysis-ltd.co.uk (Sak Wathanasin)
Date: Sat, 12 Mar 94 09:25:50 GMT
Organization: Network Analysis Ltd
In article <RANG.94Mar11224814@icicle.winternet.mpls.mn.us> (comp.sys.mac.programmer), rang@winternet.mpls.mn.us (Anton Rang) writes:
> In article <PLATYPUS.94Mar11181344@cirrus.som.cwru.edu> platypus@cirrus.som.cwru.edu (Gary Kacmarcik) writes:
> >while i agree that handles are useful. pointers _can_ be resizable.
> > [ ... example of re-allocating pointers, pass in ptr, pass out ptr ... ]
>
> The problem with re-allocating a pointer using such a routine is
> that it doesn't update any *other* pointers to the same memory block.
> So if you have a data structure whose size needs to change, you need
> to track every pointer to it. At that point, you're just re-inventing
> handles.
> --
> Anton Rang (rang@winternet.mpls.mn.us)
And, of course, it's considered an "advanced C++ idiom"* these days to
use ptrs to objects that may not actually be there. Variously known as
smart pointers, envelopes &c (yes, I know they are not exactly the
same), they can used to implement persistent objects, smart memory
allocation and deallocation, bounds checking on access and so on. Mac
OS handles are a special case of these.
Anyone remember Iliffe's "Basic machine"? (That's "basic" as in
"fundamental", not "BASIC" as in "programming language".) Mostly a
paper design, but some of the ideas were implemented in the Burroughs
Algol engines. And capability-based systems? The "descriptor
registers" in ICL 2900/MU5 architectures? (Oh dear! showing my age :-)
The more things change,...
* Coplien: Advanced C++ Programing Styles and Idioms
Alger: "C++ for gurus" in latest issue of Frameworks
Sak Wathanasin
Network Analysis Limited
178 Wainbody Ave South, Coventry CV3 6BX, UK
Internet: sw@network-analysis-ltd.co.uk
uucp: ...!uknet!nan!sw AppleLink: NAN.LTD
Phone: (+44) 203 419996 Mobile:(+44) 850 587411 Fax: (+44) 203 690690
+++++++++++++++++++++++++++
>From peirce@outpost.SF-Bay.org (Michael Peirce)
Date: Sat, 12 Mar 94 09:31:56 PST
Organization: Peirce Software, Inc.
platypus@cirrus.som.cwru.edu (Gary Kacmarcik) writes:
>while i agree that handles are useful. pointers _can_ be resizable.
>for example, the following routine:
>int ReallocPtr(Ptr *p,Size newSize) {
> ...
> return(0);
> }
Two problems:
(1) This works OK if you have basically unlimited memory
available to you. If you don't, you can easily run into a
situation where you have a memory block of size N and free memory
of size N and you want to increase the size of your memory
block. In this case you can't allocate a new block until you
deallocate your old block which you can't do. With Handles, you
can move stuff around so that you can simply extend the size of
your memory block.
(2) I haven't seen a good way to get the size of the memory
block pointed at by a pointer. Using GetHandleSize() on the
Mac is quite useful.
Handles aren't nirvana, but I personally don't want to give them up.
-- Michael Peirce -- peirce@outpost.sf-bay.org
-- Peirce Software, Inc. -- 719 Hibiscus Place, Suite 301
-- -- San Jose, California USA 95117
-- Makers of: Smoothie & -- voice: +1.408.244.6554 fax: +1.408.244.6882
-- Peirce Print Tools -- AppleLink: peirce & America Online: AFC Peirce
+++++++++++++++++++++++++++
>From resnick@cogsci.uiuc.edu (Pete Resnick)
Date: Sat, 12 Mar 1994 14:18:53 -0600
Organization: University of Illinois at Urbana-Champaign
In article <CNjbKKKX.qef4bx@outpost.SF-Bay.org>, peirce@outpost.SF-Bay.org
(Michael Peirce) wrote:
>(2) I haven't seen a good way to get the size of the memory
>block pointed at by a pointer. Using GetHandleSize() on the
>Mac is quite useful.
Uh, GetPtrSize? (IM II-37, top of the page)
pr
--
Pete Resnick (...so what is a mojo, and why would one be rising?)
Graduate assistant - Philosophy Department, Gregory Hall, UIUC
System manager - Cognitive Science Group, Beckman Institute, UIUC
Internet: resnick@cogsci.uiuc.edu
+++++++++++++++++++++++++++
>From gurgle@netcom.com (Pete Gontier)
Date: Sat, 12 Mar 1994 22:52:04 GMT
Organization: cellular
u9119523@sys.uea.ac.uk (Graham Cox) writes:
>In the original (non C++) implementation of the THINK class library
>objects WERE handles. Did the programmer care? No- the indirection was
>hidden from the programmer. Upshot- easy to write syntax PLUS efficient
>memory management. In C++ I believe that objects are pointers. What
>difference does it make to the programmer?- none. The syntax is
>identical. The code is portable. However the fragmentation problem is
>still there, and presumably C++ apps either suffer as a result or have
>their own memory management code.
Try multiple inheritance with a handle-based object. Pass the address
of an object member field to a trap which moves memory. The portability
between the two schemes is *not* transparent.
>Personally, though I'm very much sold on OOP, I still like and
>appreciate handles, and would prefer that C++ implemented object as
>handles.
Me too. It must be difficult, though, as at least three compilers have
failed to support it.
--
Pete Gontier, CTO, Integer Poet Software; gurgle@netcom.com
+++++++++++++++++++++++++++
>From gurgle@netcom.com (Pete Gontier)
Date: Sat, 12 Mar 1994 22:53:23 GMT
Organization: cellular
peirce@outpost.SF-Bay.org (Michael Peirce) writes:
>(2) I haven't seen a good way to get the size of the memory block
>pointed at by a pointer. Using GetHandleSize() on the Mac is quite
>useful.
GetPtrSize works. Writing your own glue to store the size works.
--
Pete Gontier, CTO, Integer Poet Software; gurgle@netcom.com
+++++++++++++++++++++++++++
>From hammett@sbsu1.auckland.ac.nz (Tim Hammett)
Date: 13 Mar 1994 20:15:22 GMT
Organization: University of Auckland
peirce@outpost.SF-Bay.org (Michael Peirce) writes:
>(1) This works OK if you have basically unlimited memory
>available to you. If you don't, you can easily run into a
>situation where you have a memory block of size N and free memory
>of size N and you want to increase the size of your memory
>block. In this case you can't allocate a new block until you
>deallocate your old block which you can't do. With Handles, you
>can move stuff around so that you can simply extend the size of
>your memory block.
I'm not sure I follow you here. His routine tries a SetPtrSize() first,
which will attempt to increase the size of the pointed-to block without
moving it (possibly by moving relocatable stuff after the block). He only
copies if SetPtrSize() can't do its stuff. This is exactly the same as
what would happen if you were trying to resize a handle (except
SetHandleSize() will move your block if it can't resize in situ).
The only objection I can see is that by using pointers exclusively,
there isn't likely to be much the memory manager can do to move things
out of the way to resize a block in place (because almost eveything
else in the heap will be non-movable). Also Anton's point about invalid
pointers was a good one.
>(2) I haven't seen a good way to get the size of the memory
>block pointed at by a pointer. Using GetHandleSize() on the
>Mac is quite useful.
There's actually a GetPtrSize() routine. (It makes sense that there should
be one, since the memory manager needs to keep info about the size of
blocks, even if they're non-relocatable, so that it can walk the heap).
(As for stuff allocated using malloc(), that's another story).
--
Tim Hammett, School of Biological Sciences, Auckland University, New Zealand.
t.hammett@auckland.ac.nz Phone: +64-9-373-7599 x8365 FAX: +64-9-373-7416
+++++++++++++++++++++++++++
>From sew@design.canberra.edu.au (Simon Ward)
Date: Mon, 14 Mar 94 03:58:51 GMT
Organization: University of Canberra
In article <j-norstad-040394184108@aragorn12.acns.nwu.edu> John Norstad,
j-norstad@nwu.edu writes:
>SetHandleSize(h, GetHandleSize(h) + n) is one of my favorite lines of C on
>the Mac, and is one of the many reasons I find programming the Mac to be
>much more fun and pleasant than programming other kinds of computers.
I agree, it's a very flexible way of dealing with a user's data
structures that are of an indeterminate size. Pointers can't offer the
same flexiblity.
Simon Ward
sew@design.canberra.edu.au
+++++++++++++++++++++++++++
>From ivanski@world.std.com (Ivan M CaveroBelaunde)
Date: Mon, 14 Mar 1994 15:40:35 GMT
Organization: The World Public Access UNIX, Brookline, MA
peirce@outpost.SF-Bay.org (Michael Peirce) writes:
>platypus@cirrus.som.cwru.edu (Gary Kacmarcik) writes:
>>for example, the following routine:
>>int ReallocPtr(Ptr *p,Size newSize) {
>> ...
>> return(0);
>> }
>Two problems:
> ( ... deleted ...)
Additionally, this also presents the same problem that the concept
of master pointers in handles were intended to solve - namely,
that the block of memory could be moved but the number the program
used to identify that (the handle) need not change. If I hand off
the above pointer to some other block of my program and then call
ReallocPtr, the other block is left holding a reference to a stale
pointer, something that does not happen with handles.
-Ivan
- -
Ivan Cavero Belaunde (ivanski@world.std.com)
Avid VideoShop Project Lead
Avid Technology, Inc.
+++++++++++++++++++++++++++
>From ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University)
Date: 14 Mar 94 17:37:10 +1300
Organization: University of Waikato, Hamilton, New Zealand
In article <199403082216.RAA07098@wolverine.cs.rochester.edu>, Brad Miller <miller@cs.rochester.edu> writes:
>
> Handles shouldn't be needed with any "real" VM.
>
Gee, and after all the comments from people pointing out how useful handles
are for creating resizable objects. How does virtual memory help deal with
this?
Lawrence D'Oliveiro fone: +64-7-856-2889
Info & Tech Services Division fax: +64-7-838-4066
University of Waikato electric mail: ldo@waikato.ac.nz
Hamilton, New Zealand 37^ 47' 26" S, 175^ 19' 7" E, GMT+13:00
+++++++++++++++++++++++++++
>From ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University)
Date: 14 Mar 94 17:59:05 +1300
Organization: University of Waikato, Hamilton, New Zealand
In article <PLATYPUS.94Mar11181344@cirrus.som.cwru.edu>,
platypus@cirrus.som.cwru.edu (Gary Kacmarcik) reminds everyone about
SetPtrSize.
Sure, this call exists. But how often is it likely to succeed? I can't imagine
the Memory Manager deliberately goes about leaving gaps between successively-
allocated blocks. Thus, it seems to me it's going to fail on the vast majority
of calls.
Your sample code did check for this situation, and if the pointer resize failed,
it allocated a new block and deallocated the old one. Now, what happens if
you have several bits of code wanting access to the data? Answer: you must
maintain a single master pointer to the block. What if the clients don't know
where the master pointer is? Answer: you give them a pointer to the master
pointer. Congratulations! You've just reinvented handles, only you're not going
to do it as efficiently as the Memory Manager can.
Lawrence D'Oliveiro fone: +64-7-856-2889
Info & Tech Services Division fax: +64-7-838-4066
University of Waikato electric mail: ldo@waikato.ac.nz
Hamilton, New Zealand 37^ 47' 26" S, 175^ 19' 7" E, GMT+13:00
+++++++++++++++++++++++++++
>From rabeet@aol.com (Rabeet)
Date: 14 Mar 1994 23:48:03 -0500
Organization: America Online, Inc. (1-800-827-6364)
Here's a simple solution to the argument: sit down, learn how to deal with
handles and what they are really good for. End of argument.
I have long since given up on handles for C++ objects (love mix-ins and
embedded objects), which aren't of variable size anyway, but anyone doing
serious Mac development uses them for a large portion of everything else.
Edward Harp
Rocket Science Games, Inc.
Disclaimer: my opinions aren't rocket science
+++++++++++++++++++++++++++
>From nagle@netcom.com (John Nagle)
Date: Tue, 15 Mar 1994 17:45:08 GMT
Organization: NETCOM On-line Communication Services (408 241-9760 guest)
ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University) writes:
>In article <199403082216.RAA07098@wolverine.cs.rochester.edu>, Brad Miller <miller@cs.rochester.edu> writes:
>>
>> Handles shouldn't be needed with any "real" VM.
>>
Handles would be more useful if they were properly supported in
compilers. Many Mac compilers dereference handles without locking
them, which is dumb. This started with Pascal, where "with" statements
dereference handles, and you're supposed to know that you have to lock
them before doing a "with" statement, unless you're sure the clauses of
the "with" statement can't move memory. It got worse in C++, where
there's the possibility that someone may subclass a function previously
"safe" with regard to moving memory and make it unsafe. There's also
a serious problem with handle objects that contain non-handle objects
with constructors; SC++ will call a constructor for a subobject with
the main object dereferenced and unlocked. If the compiler does a
dereference on its own, the compil tuff
right on top of it.
- Did I mention all those yechy possibilities? What if the depth of
the monitor somehow gets changed in the middle of your program? Youch.
- It's very low-level and a headache. You'll be rebooting quite
frequently as you try to figure it out. In Quickdraw, if you write
outside the boundary of a window, it's nicely clipped for you. Nothing
bad happens. If you're writing to video RAM and you go off the screen,
well, the best you can hope for is an exciting crash instead of a
silent freeze.
Advantages:
- Many other programmers will congratulate you for ignoring the wimps
who say "tsk, tsk."
- If you know what you're doing, you can see some serious speed in certain
circumstances.
- Hey, a lot of people do it. Lots of games. Lots of commercial programs.
Heck, even System 7 does it!
- Enough people have done it to come up with a list of "rules" to follow;
it's not black magic as it once used to be. (Again, find that Develop
article.)
- It will give you an opportunity to really understand what's going on
with the video in your Mac. And I get a pleasure out of refining my
code to make it quicker and quicker. It's fun to develop methods for
masking, etc. You gain speed by writing routines specific to your
needs. While CopyBits will do just about anything, you might find
youself writing 10 different versions for different situations.
- It will work with the PowerPC, so you're safe for now.
- All that rebooting will let you see that friendly smiling Mac more times
a day.
I suppose I might get around to posting a simple class I wrote in C++
that let's you attack direct-screen drawing in a slightly less intimidating
manner, on alt.sources.mac. But I must admit right now I'm not doing
the 32-bit or ShieldCursor tricks. Heck, I don't need to. Works fine
on my Mac right now.. So I'd need to clean it up a bit first.
Good luck!
Scott
- -
M. Scott Smith (mssmith@afterlife.ncsc.mil || umsmith@mcs.drexel.edu)
Macintosh developer, student, ski bum. Eater of Cinnamon Toast Crunch.
"Last stop for fuel on the information superhighway."
+++++++++++++++++++++++++++
>From jwbaxter@olympus.net (John W. Baxter)
Date: Mon, 28 Feb 1994 22:15:19 -0800
Organization: Internet for the Olympic Peninsula
In article <rwparkerCLyJqB.6nD@netcom.com>, rwparker@netcom.com (Richard W.
Parker) wrote:
> Does anyone know of a "generally-accepted" method for writing directly to
> screen memory? I am looking for a method that will work across most of the
> 32-bitQD Macintoshes.
>
> Also - what are the pros and cons in doing so? Is CopyBits fast enough not
> to worry about it?
I don't think this is the time to be exploring direct writing to screen
memory. Too much is happening "real soon now": (1) powerPC, and (2) more
important here, QuickDraw GX.
The time spent mastering direct writing can probably be better spent
learning QD GX (even though the latter won't be in every Mac for a while).
--
John Baxter Port Ludlow, WA, USA [West shore, Puget Sound]
jwbaxter@pt.olympus.net
+++++++++++++++++++++++++++
>From d88-jwa@mumrik.nada.kth.se (Jon Wdtte)
Date: 1 Mar 1994 19:20:51 GMT
Organization: Royal Institute of Technology, Stockholm, Sweden
>> Does anyone know of a "generally-accepted" method for writing directly to
>> screen memory? I am looking for a method that will work across most of the
>> 32-bitQD Macintoshes.
>I don't think this is the time to be exploring direct writing to screen
>memory. Too much is happening "real soon now": (1) powerPC, and (2) more
>important here, QuickDraw GX.
None of these will impact direct-to-screen-drawing in the near
future. If you mean the PowerPC will be fast enough to not need
direct-to-screen (and the same for QDGX) then consider the
large installed base of Performas which will NOT be PowerPC
upgraded anytime soon, and QDGX will not be faster than QD for
bitmap-type things, just better :-)
>The time spent mastering direct writing can probably be better spent
>learning QD GX (even though the latter won't be in every Mac for a while).
Not if what he wants to do is write an arcade game.
--
-- Jon W{tte, h+@nada.kth.se, Mac Hacker Deluxe --
"Don't use the Layer Manager"
+++++++++++++++++++++++++++
>From ingemar@lysator.liu.se (Ingemar Ragnemalm)
Date: Fri, 4 Mar 1994 10:52:11 GMT
Organization: (none)
mssmith@afterlife.ncsc.mil (M. Scott Smith) writes:
> What are the advantages and disadvantages of messing around with the
>video RAM?
>Disadvantages:
> - Many programmers will frown upon you and say "Tsk, tsk."
> - You may not need to for speed, anyway.
For games, we generally do.
> - You're playing with a loaded gun in terms of ensuring compatibility with
> future Macs.
> - You've got to take it upon yourself to deal with all kinds of yechy
> "possibilities" that QuickDraw normally handles for you (such as.. the
> Radius Pivot.)
An option to use it or use QuickDraw instead isn't too bad. It's hard for
the program to tell if it will work, but at least the user can make it work
if he/she has hardware where it doesn't.
> - You give up the Mac interface, unless you're really tricky. For example,
> you won't be drawing in a window, so the user can't move your drawing
> across the screen... or from one monitor to another.. And System 7
> doesn't know about your drawing so it's perfectly happy to throw stuff
> right on top of it.
That means only a few drawbacks. Make the window non-moveable, and only use
the direct-to-screen routines when it's the front window.
> - Did I mention all those yechy possibilities? What if the depth of
> the monitor somehow gets changed in the middle of your program? Youch.
Did anyone notice how SAT switches depth automatically? :-)
> - It's very low-level and a headache.
This is *true*. :-(
>Advantages:
(Deleted - but speed is what counts)
--
- -
Ingemar Ragnemalm, PhD
Image processing, Mac shareware games
E-mail address: ingemar@isy.liu.se or ingemar@lysator.liu.se
---------------------------
>From Tony Andreoli <Tony_Andreoli_-_CTA@CL_63SMTP_GW.CHINALAKE.NAVY.MIL>
Subject: dirIDs
Date: Wed, 9 Mar 1994 15:23:21 GMT
Organization: Naval Air Warfare Center - Weapons Division
Here is my question...I am in the home folder of an application and I
know the name of a
folder in the same directory. How can I obtain the dirID of the
directory so that I can do
a PBGetCatInfo on that directory.
thanx for the help...
+++++++++++++++++++++++++++
>From Steve Bryan <sbryan@maroon.tc.umn.edu>
Date: Mon, 14 Mar 1994 16:23:54 GMT
Organization: Sexton Software
In article <CMELEx.CG0@avalon.chinalake.navy.mil> Tony Andreoli,
Tony_Andreoli_-_CTA@CL_63SMTP_GW.CHINALAKE.NAVY.MIL writes:
>Here is my question...I am in the home folder of an application and I
>know the name of a
>folder in the same directory. How can I obtain the dirID of the
>directory so that I can do
>a PBGetCatInfo on that directory.
When your program is starting up call CurResFile to identify the refNum
of the resource fork of your application. Call PBGetFCBInfo with ioRefNum
set to your resource fork refNum and ioFCBIndx set to zero. It will
return a bunch of info including the parID for the folder containing your
application. Note that there is at least one other method for obtaining
the refNum of your application which may be less likely to break which is
a call to GetAppParms. I mentioned the other way because that is what I
use.
---------------------------
>From jaeger@kunikpok.icus.com (Jaeger)
Subject: jGNEFilter Q
Date: Fri, 11 Mar 94 10:56:26 CST
Organization: Kunikpok Kennels and Komputers (Pet Project)
HereUs a question for any jGNEFilter gurus out there: Is there any time
that it is safe for a jGNEFilter to uninstall itself? For instance, if
the value stored in the global jGNEFilter is equal to your own entry
point is it safe to uninstall yourself. Also, is it safe for an init to
install a jGNEFilter at other than init time? If you do that will it be
removed by the finder when the app that was running when the filter was
installed quits? IUm assuming that the finder maintains the jGNEFilter
global as part of the lo-mem world that is alterred when the context is
switched.
Brian Stern :-{)}
Jaeger@fquest.com
+++++++++++++++++++++++++++
>From gurgle@netcom.com (Pete Gontier)
Date: Fri, 11 Mar 1994 23:31:13 GMT
Organization: cellular
jaeger@kunikpok.icus.com (Jaeger) writes:
>HereUs a question for any jGNEFilter gurus out there: Is there any time
>that it is safe for a jGNEFilter to uninstall itself? For instance, if
>the value stored in the global jGNEFilter is equal to your own entry
>point is it safe to uninstall yourself.
Maybe. Assuming no one is trying to trick you with a skanky hack.
>Also, is it safe for an init to install a jGNEFilter at other than init
>time?
>From what I hear on the net, it is even safe for an application to
install a jGNEFilter -- and it will apply to all apps. Of course, the
difficult part for an application is how to uninstall the filter when
quitting.
>If you do that will it be removed by the finder when the app that was
>running when the filter was installed quits?
No.
>IUm assuming that the finder maintains the jGNEFilter global as part of
>the lo-mem world that is alterred when the context is switched.
>From what I have heard on the net, this is not the case.
--
Pete Gontier, CTO, Integer Poet Software; gurgle@netcom.com
+++++++++++++++++++++++++++
>From urge@mcl.ucsb.edu (Scott Bronson)
Date: 12 Mar 1994 00:53:47 GMT
Organization: University of California, Santa Barbara
In <Rw91ic1w165w@kunikpok.icus.com> jaeger@kunikpok.icus.com (Jaeger) writes:
>HereUs a question for any jGNEFilter gurus out there: Is there any time
>that it is safe for a jGNEFilter to uninstall itself? For instance, if
>the value stored in the global jGNEFilter is equal to your own entry
>point is it safe to uninstall yourself.
Theoretically, once you've stored a value in JGNEFilter, you can never
go back. While it's probably 99.9999% safe to deinstall your jGNE,
I personally would not (and did not). Instead, I've installed a tiny,
locked code resource in the Sytem Heap that would communicate with a
Gestalt selector to indicate what it should do with the incoming events.
Using a jGNE/Gestalt tandem also means you only have to install once,
because you can use it from then on (it's immune to application launches,
quits, ...)
Please note: each installed jGNE slows down the machine's perceived
speed--it will take longer between the time the user clicks the mouse
and the button highlights. The Mac is already slower than other machines
in this respect, so *please* do as little processing as possible at jGNE
time.
>Also, is it safe for an init to
>install a jGNEFilter at other than init time? If you do that will it be
>removed by the finder when the app that was running when the filter was
>installed quits? IUm assuming that the finder maintains the jGNEFilter
>global as part of the lo-mem world that is alterred when the context is
>switched.
Yes, it is safe to install a jGNE after INIT time. Just make sure to
install your proc in the System Heap because it will never be uninstalled
(except perhaps by you, which is bad for reasons previously mentioned).
The jGNE will be called for EVERY event, not just events that belong to
the application that installed it. This is a very effecitve way of
slurping events destined for other apps; I've used this technique before.
A low-level debugger and some patience are all that's required. Have
fun with it.
- Scott
+++++++++++++++++++++++++++
>From moofster@world.std.com (A Happy Dog-Cow)
Date: Sat, 12 Mar 1994 09:32:08 GMT
Organization: The Nest of the Moofster
In general, if TrapAddress(patchedTrap/Vector) == (yourHandler)
Then it's safe to de-install. With very few exceptions, this is
the case for all traps & low-memory vectors.
I ditto earlier comments about keeping gneFilter processing to
an absolute minimum.
Robert M. Seretny, Armesti Research
+++++++++++++++++++++++++++
>From jlscott@tigr.org (John L. Scott)
Date: 15 Mar 1994 11:17:28 -0600
Organization: Self
In article <Rw91ic1w165w@kunikpok.icus.com>, jaeger@kunikpok.icus.com
(Jaeger) wrote:
> I'm assuming that the finder maintains the jGNEFilter
> global as part of the lo-mem world that is alterred when the context is
> switched.
Don't assume that. jGNEFilter is _not_ altered when the context is
switched.
--John
---------------------------
>From cverret@vnet3.vub.ac.be (Chris Verret)
Subject: password encryption
Date: Tue, 08 Mar 1994 15:54:07 +0100
Organization: Vrije Universiteit Brussel
I suppose most users would appreciate it when an application
encrypts passwords before they are placed in a preference file.
So does anyone perharps know where I can find a straightforward
snippet for encryption/decryption of passwords?
PS: recently some queries were posted concerning the bulleting of
password textitems. Its very simple to write a short filter for
this. If anyone is still needs this, I'm always prepared to mail
a short example.
--
__________________________________________________________________________
Chris Verret cverret@vnet3.vub.ac.be
+++++++++++++++++++++++++++
>From zobkiw@datawatch.com (joe zobkiw)
Date: Wed, 9 Mar 1994 14:40:09 GMT
Organization: Datawatch Corporation
In article <cverret-080394155407@progmc39.vub.ac.be>,
cverret@vnet3.vub.ac.be (Chris Verret) wrote:
> I suppose most users would appreciate it when an application
> encrypts passwords before they are placed in a preference file.
>
> So does anyone perharps know where I can find a straightforward
> snippet for encryption/decryption of passwords?
This code is from NewsWatcher...it works nicely...
/*----------------------------------------------------------------------------
ScramblePassword
Scrambles (and unscrambles) saved passwords. This is not really secure,
just something to foil people browsing using disk editors.
Entry: pw = the password.
len = length of password.
Exit: Each byte nibble-swapped and bit-flipped.
- --------------------------------------------------------------------------*/
void ScramblePassword(unsigned char *password, short len)
{
unsigned char *p, *pEnd;
pEnd = password + len;
for (p = password; p < pEnd; p++)
*p = (((*p >> 4) & 0x0f) | ((*p & 0x0f) << 4)) ^ 0xff;
}
___________________________________________________________
_/_/_/_/ Joe Zobkiw ,,,
_/ Senior Software Engineer - -
_/ Datawatch Corporation L
_/_/_/_/ zobkiw@datawatch.com -
+++++++++++++++++++++++++++
>From sholmes@netrix.com (Stephen R Holmes)
Date: Fri, 11 Mar 1994 17:03:32 GMT
Organization: Netrix Corporation
In article <cverret-080394155407@progmc39.vub.ac.be>,
cverret@vnet3.vub.ac.be (Chris Verret) wrote:
> I suppose most users would appreciate it when an application
> encrypts passwords before they are placed in a preference file.
>
> So does anyone perharps know where I can find a straightforward
> snippet for encryption/decryption of passwords?
Actual _encryption_ may not really be necessary; encryption sort of
implies that you'll want to recover the original value from the
encrypted result. For passwording, all you really [may] want is to
verify that the entered password is the same as the original; to
do so with reasonable assurance, it may only be necessary to "hash"
the original password, then "hash" all subsequent entries to see
if the hash-value is the same as the one stored. Simple example:
unsigned long hash_pwd (char *pwd)
{
unsigned long hash = 0x31415926;
while (*pwd)
hash = (hash<<1) + *pwd++;
return (hash);
}
The mathematically-inclined out there may be able to tell us what
the probability of two distinct passwords having the same hash-value
is, but the intuitive answer is 'pretty darn small' :-) Naturally,
your routine would refuse to accept 1- or 2-character passwords...
/srh
--
Stephen R. Holmes | sholmes@netrix.com | the usual disclaimers
Netrix Corporation | srh@netrix.com | .....
Herndon, VA USA | srholmes@aolcom | witty saying TBD
---------------------------
End of C.S.M.P. Digest
**********************